IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LeetCode初级算法-数组 -> 正文阅读

[数据结构与算法]LeetCode初级算法-数组

初级算法

一、删除排序数组的重复项

题目:给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

示例1:
输入:nums = [1,1,2]
输出:2, nums = [1,2]

解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

/**
* count记录元素重复数 == 数组元素向前移动的步数
*/
 public int removeDuplicates(int[] nums) {
        int count = 0;
        for (int i = 1; i < nums.length; i++) {
            if(nums[i] == nums[i - 1]){
                count ++;
            }else {
                nums[i - count] = nums[i];
            }
        }
        return nums.length - count;
    }

二、买卖股票的最佳时机

给定一个数组 prices ,其中?prices[i] 是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

示例:
输入: prices = [7,1,5,3,6,4]
输出: 7

解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
? 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3

解法1:

  public static int maxProfit(int[] prices) {
        int money = 0;
        if(prices == null || prices.length < 2){
            return 0;
        }
        boolean a = true; //标志位 记录递增 递减的变化
        for (int i = 0; i < prices.length - 1; i++) {
            if(prices[i] >= prices[i + 1] && !a){
                money = money + prices[i];
                a = true;
            }
            if(prices[i] < prices[i + 1] && a){
                money = money - prices[i];
                a = false;
            }
        }
        //末位判断递增or递减  递增则收益
        if(prices[prices.length - 1] > prices[prices.length - 2]){
            money = money + prices[prices.length - 1];
        }
        return money;
    }

三、旋转数组

问题:数组中元素向右轮转k个位置,其中k是非负数

案例1:
int[] array = {1,2,3,4,5,6,7,8,9,10};
k 旋转位数

k = 3
输出:[8,9,10,1,2,3,4,5,6,7]

public static int[] xuanZhuan(int[] array,int k){
        int[] temp = array.clone();
        for (int i = 0; i < array.length; i++) {
            int a = (i + k) % array.length;
            array[a] = temp[i];
        }
        return array;
    }

四、存在重复元素

给定一个整数数组,判断是否存在重复元素。

如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。

示例 1:

输入: [1,2,3,1]
输出: true
示例 2:

输入: [1,2,3,4]
输出: false
示例3:

输入: [1,1,1,3,3,4,3,2,4,2]
输出: true

解法1:暴力

public static boolean method(int[] array){
        if(array == null){
            return true;
        }
        for (int i = 0; i < array.length; i++) {
            for (int j = i + 1; j < array.length; j++) {
                if(array[j] == array[i]){
                    return true;
                }
            }
        }
        return false;
    }

解法2:
利用set集合特性
set中不能有重复的元素,添加相同元素失败

 public static boolean containsDuplicate(int[] nums) {
        Set<Integer> set = new HashSet<>();
        for (int num : nums) {
            if (!set.add(num))
                return true;
        }
        return false;
    }

解法3:
先排序后比较前后元素是否一致

 public static boolean containsDuplicate(int[] nums) {
        Arrays.sort(nums);
        for(int i = 0; i < nums.length - 1; i++) {
            if (nums[i] == nums[i + 1]) {
                return true;
            }
        }
        return false;
    }

五、只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

示例:
输入: [4,1,2,1,2]
输出: 4

思路:使用异或运算,将所有值进行异或

public int singleNumber(int[] nums) {
        int reduce = 0;
        for (int num : nums) {
            reduce =  reduce ^ num;
        }
        return reduce;
    }

六、两个数组的交集

给你两个整数数组?nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

示例:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]

思路:先对两个数组进行排序,后判断

public static int[] intersect(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        ArrayList<Integer> list = new ArrayList<>();
        int i = 0,j = 0;
        while (i < nums1.length && j <nums2.length) {
            if(nums1[i] < nums2[j]){
                i ++;
            }else if(nums1[i] > nums2[j]){
                j ++;
            }else {
                list.add(nums1[i]);
                i ++;
                j ++;
            }
        }
        int[] target = new int[list.size()];
        for (int z = 0; z < list.size(); z++) {
            target[z] = list.get(z);
        }
        return target;
    }

七、加一

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例:
输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。
数组所有元素看成是一个数字:123 + 1 = 124
9 + 1 = 10
99 + 1 = 100
235 + 1 = 236

解决:

 public static int[] plusOne(int[] digits) {
        //找到末位元素是9的进行操作
        if(digits[digits.length - 1] == 9){
            for (int i = digits.length - 1; i >= 0; i--) {
                if(digits[i] == 9){
                    //元素是9 则当前元素置0
                    digits[i] = 0;
                }else {
                    //只要期间有一个元素不为9 则可返回
                    digits[i] ++;
                    return digits;
                }
            }
            int[] temp = new int[digits.length + 1];
            temp[0] = 1;
            return temp;
        }
        //末位元素不是9 则直接++
        digits[digits.length - 1] ++;
        return digits;
    }

八、移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

解法1:

 public static void moveZeroes(int[] nums) {
        //记录0出现个数
        int pos = 0;
        for (int i = 0; i < nums.length; i++) {
            if(nums[i] == 0){
                pos ++;
            }else if(pos > 0){
                //元素向前移动
                nums[i - pos] = nums[i];
            }
        }
        if(pos > 0){
            //最后元素置0
            for (int i = 1; i <= pos; i++) {
                nums[nums.length - i] = 0;
            }
        }
    }

解法2:

public static void moveZeroes2(int[] nums) {
        int pos = 0;
        //非0元素向前移动
        for (int i = 0; i < nums.length; i++) {
            if(nums[i] != 0){
                nums[pos ++] = nums[i];
            }
        }
        //最后num.length - pos 个的元素置0
        while(pos < nums.length){
            nums [pos++] = 0;
        }
    }

九、两数之和

给定一个整数数组 nums?和一个整数目标值 target,请你在该数组中找出 和为目标值 target? 的那?两个?整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

实例1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

解法1:暴力算法

//暴力算法
    public static int[] twoSum(int[] nums, int target){
        for (int i = 0; i < nums.length; i++) {
            for (int j = i + 1; j < nums.length; j++) {
               if(nums[i] + nums[j] == target){
                   return new int[]{i,j};
               }
            }
        }
        return new int[]{-1,-1};
    }

解法2:HashMap
思路:
新建一个HashMap存储元素
存储方式:key(存储元素值):nums[i],value(存储数组下标):i
判断条件 m.get(target - nums[i]) != null,其中target - nums[i]得到是与之匹配的第二个元素值,假如能HashMap中找到对应的key则说明存在该两个元素之和等于target,同时也可得到对应元素的数组下标。

    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> m = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if (m.get(target - nums[i]) != null) {
                return new int[]{m.get(target - nums[i]), i};
            }
            m.put(nums[i], i);
        }
        return new int[]{0, 0};
    }

十、有效的数独

请你判断一个?9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

数字?1-9?在每一行只能出现一次。
数字?1-9?在每一列只能出现一次。
数字?1-9?在每一个以粗实线分隔的?3x3?宫内只能出现一次。(请参考示例图)

注意:

一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
空白格用?‘.’?表示。

示例1:
输入:
 char[][] board  = {{'8','3','.','.','7','.','.','.','.'}
                        ,{'6','.','.','1','9','5','.','.','.'}
                        ,{'.','9','8','.','.','.','.','6','.'}
                        ,{'8','.','.','.','6','.','.','.','3'}
                        ,{'4','.','.','8','.','3','.','.','1'}
                        ,{'7','.','.','.','2','.','.','.','6'}
                        ,{'.','6','.','.','.','.','2','8','.'}
                        ,{'.','.','.','4','1','9','.','.','5'}
                        ,{'.','.','.','.','8','.','.','7','9'}};

输出:false

解法1:暴力解
思路:

  • line col box三张二维表作用是记录元素占用的位置
  • line表可以看做是原board[][]字符数组表
  • col表的行可以当做是line表中的列
  • box表的行可以看做是,原board[][]字符数组的3x3单元格(9x9宫格分成9个3x3单元格,从左往右按顺序排列)
  • 单元格如下表示:
  • pos0,pos1,pos2,
  • pos3,pos4,pos5,
  • pos6,pos7,pos8
  • 三张表元素按照指定的排序规则,排序在表内
  • 即相同元素的排序位置是固定的
  • 举个例子,在board[0][]字符数组第一行内有两个相同的元素[,9,3,4,6,8,9]
  • 可以看出上述有相同元素9,即board[0][1] = 9 ,board[0][8] = 9
  • 我们根据排序规则 int pos = board[i][j] - ‘1’;
  • pos = board[0][1] - ‘1’ = 8
  • pos = board[0][8]- ‘1’ = 8
  • 得到pos都是等于8,所以当第一次位置未被占用时,board[0][1]的元素占用该位置,
  • 在执行到board[0][8]时,发现位置已经被占用,所以这是一个无效的数独
public static boolean isValidSudoku(char[][] board){
        //存储行的二维数组
        int[][] line = new int[board.length][board[0].length];
        //存储列的二维数组
        int[][] col = new int[board.length][board[0].length];
        //存储单元的二维数组
        int[][] box = new int[board.length][board[0].length];

        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                //board二维字符数组中'.'表示没有元素,所以可以直接跳过
                if(board[i][j] == '.')continue;
                //数组下标是0-8 所以pos代表的是排序后元素的位置
                //board[i][j] - '1'的区间是[0-8](不懂的小伙伴可以查看ASCII表对应值),对应这排序后的数组下标
                int pos = board[i][j] - '1';
                //首先将9x9的宫格分成9个3x3的单元格,从左到右排序
                //boxIndex代表的是从左到右的单元格的位置,boxIndex的范围是[0,8]
                int boxIndex = i/3 * 3 + j/3;
                //判断二维数组中位置是否已经被占用(二维数组中没有元素的值默认为0)
                if((line[i][pos] != 0) || (col[j][pos] != 0) || (box[boxIndex][pos] != 0))return false;
                //位置没有被占用,即可设置固定值 1 表示该位置已经被占用
                line[i][pos] = col[j][pos] = box[boxIndex][pos] = 1;
            }
        }
        return true;
    }

十一、旋转图像

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]

解法1:
思路:首先将二维矩阵上下对称交换,然后按照对角线交换

123                789                741
456   对称交换--->  456   对角线交换---> 852  
789                123                963
public static void rotate(int[][] matrix) {
        //调换位置 上下
        for (int i = 0; i < matrix.length / 2; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[matrix.length - 1 - i][j];
                matrix[matrix.length - 1 - i][j] = temp;
            }
        }
        //调换位置 对角线
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if(i == j)break;
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
    }
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章           查看所有文章
加:2021-12-20 17:55:42  更:2021-12-20 17:56:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:23:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码