数组(二):大厂面试不得不看的高频数组类型题目


不要纠结,干就完事了,熟练度很重要!!!多练习,多总结!!!

LeetCode905:按奇偶排序数组

给定一个非负整数数组 A,返回一个数组,在该数组中, A 的所有偶数元素之后跟着所有奇数元素。你可以返回满足此条件的任何数组作为答案。

解题思路

我们可以引入一个指针j用来存放数组中所有偶数的元素,j默认初始化为0,同时遍历数组寻找偶数元素,找到后,我们将当前位置元素与指针j指向元素进行交换,然后指针后移,同时继续遍历元素!相当于指针j负责存放我们遍历过程中寻找到的偶数元素,从索引0开始依次向后存储,这样就把偶数元素全都放在了数组前面!

代码实现

class Solution {
    public int[] sortArrayByParity(int[] A) {
        if (A==null||A.length==0){
            return A;
        }
        int index=0;
        for (int i=0;i<A.length;i++){
            if (A[i]%2==0){
                swap(A,index,i);
                index++;
            }
        }
        return A;
    }
    public void swap(int[] num,int i,int j){
        int tmp=num[j];
        num[j]=num[i];
        num[i]=tmp;
    }
}

LeetCode11:盛水最多的容器

给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

解题思路

本题是双指针的思路!双指针初始化为数组的首尾。双指针代表的高度就是容器的两边,盛水的多少取决于最短的那个高度,所以,想要盛水多,我们每次只能让高度低的那个指针向高度高的那个指针移动,每次移动我们都计算下当前的盛水多少,将每次记录的盛水容量取最大值即可得到答案!!!

代码实现

class Solution {
    public int maxArea(int[] height) {
        int i=0,j=height.length-1;
        int res=0;
        while (i<j){
            res=height[i]<height[j]?Math.max(res,(j-i)*height[i++]):Math.max(res,(j-i)*height[j--]);
        }
        return res;
    }
}

LeetCode66:加一

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

解题思路

这题,可能会出现一种特殊情况,就是每一位均为9,那么加一进位后,位数也会多一位的!那么怎么来做呢?我们从数组最高位(相当于数字最低位)遍历元素,每次将该位元素加1后,然后对10进行取模运算,看是否为0,如果不为0,那么相当于没有进位,直接返回即可!如果为零,那么继续遍历重复上述步骤(下一位加1,再对10进行取模运算) ,如果数组遍历完都没有返回,那么就是出现了每位都是9的情况,这是只需重新new一个比原来大一位的数组,并将数组的首元素设为1即可,代表加1后进位的结果!

代码实现

class Solution {
class Solution {
    public int[] plusOne(int[] digits) {
        for (int i=digits.length-1;i>=0;i--){
            digits[i]++;
            digits[i]=digits[i]%10;
            if (digits[i]!=0){
                return digits;
            }
        }
        int[] tmp=new int[digits.length+1];
        tmp[0]=1;
        return tmp;
    }
}

LeetCode122:买卖股票的最佳时机Ⅱ

如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。注意你不能在买入股票前卖出股票。

解题思路

这是股票系列最简单的一道题了,后面我会单独开一篇文章讲解股票系列的8道题。
本题题意可以总结出两点:1.我们每次同时只能进行一笔交易,也就是你必须卖了才能再买。2.前后一共可以进行多次交易,只要卖了就能再买,收益是每笔交易的累加。
那么解决本题的思想就是低买高卖!我们只需判断相邻两次的股价是否是上涨的,上涨就买,然后进行收益累加!否则不进行任何操作。

代码实现

class Solution {
    public int maxProfit(int[] prices) {
        int sum=0;
        for (int i=1;i<prices.length;i++){
            if (prices[i]-prices[i-1]>0){
                sum+=prices[i]-prices[i-1];
            }
        }
        return sum;
    }
}

LeetCode189:旋转数组

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:

输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]

解题思路

这题题意是数组旋转,但是我们需要想的是,这个旋转操作可以通过什么变换的到?其他这个旋转操作等价于三次反转变换!对,三次!我们只需要将所有元素反转,然后反转前 k 个元素,再反转后面l-k个元素,就能得到想要的结果。
实际我们只需实现一个反转函数,反转函数就是依据两边中心进行元素的对应交换!

代码实现

class Solution {
    public void rotate(int[] nums, int k) {
        reverse(nums,0,nums.length-1);
        reverse(nums,0,k%nums.length-1);
        reverse(nums,k%nums.length,nums.length-1);
    }
    public void reverse(int[] nums,int left,int right){
        while (left<right){
            int tmp=nums[left];
            nums[left++]=nums[right];
            nums[right--]=tmp;
        }
    }
}

LeetCode350:两个数组的交集Ⅱ

给定两个数组,编写一个函数来计算它们的交集。

解题思路

我们当然可以通过hashmap来解!但是如果数组是有序的,该怎么来优化算法呢?我们借助双指针的思想,两个指针分别指向数组的初始元素,每次我们比较两指针元素的大小,如果指向arr1的元素大于arr2的元素,那么arr2的指针后移,相反,arr1的指针后移,如果相同我们记录元素并同时移动两个指针!

代码实现

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        int i=0,j=0,k=0;
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        while (i<nums1.length&&j<nums2.length){
            if (nums1[i]<nums2[j]){
                i++;
            }else if (nums1[i]>nums2[j]){
                j++;
            }else {
                nums1[k++]=nums1[i++];
                j++;
            }
        }
        return Arrays.copyOfRange(nums1,0,k);
    }
}

LeetCode27:移除元素

给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

解题思路

本题我们要做到原地删除。我们维护一个指针初始位置为0,用来记录移除过后还存活的元素,遍历数组当遍历元素不等于目标元素时,将元素记录在维护指针的位置,并将指针后移,当遇到等于目标元素时,指针不动,也就是不进行任何操作去寻找下一个不等于val的值!遍历完成后,返回指针下标即可!

代码实现

class Solution {
    public int removeElement(int[] nums, int val) {
        int j=0;
        for (int i=0;i<nums.length;i++){
            if (nums[i]!=val){
                nums[j++]=nums[i];
            }
        }
        return j;
    }
}

LeetCode26:删除排序数组中的重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

解题思路

本题思路和上体相似,同样需要维护一个指针这个指针初始化0,我们遍历从第二个开始,因为我们要找出不同的元素,相当于每次我们都要找到和指针指向的元素不同时才可以!指针指向的是前一个不重复的元素,当我们找到下一个不重复的元素时,先是指针后移,然后将当前元素复制到指针指向的元素处!依次进行,即可剔除重复元素!

代码实现

class Solution {
    public int removeDuplicates(int[] nums) {
        int j=0;
        for (int i=1;i<nums.length;i++){
            if (nums[i]!=nums[j]){
                j++;
                nums[j]=nums[i];
            }
        }
        return j+1;
    }
}

剑指offer12:矩阵中的路径

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路(路径中的字母用加粗标出)。
[[“a”,“b”,“c”,“e”],
[“s”,“f”,“c”,“s”],
[“a”,“d”,“e”,“e”]]
但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。

解题思路

DFS的搜索思路!看代码体会下

代码实现

class Solution {
    public boolean exist(char[][] board, String word) {
        if (board.length==0||word.length()==0){
            return false;
        }
        int rows=board.length,cols=board[0].length;
        char[] words=word.toCharArray();
        int[][] flag=new int[rows][cols];
        for (int i=0;i<rows;i++){
            for (int j=0;j<cols;j++){
                if (dfs(board,i,j,flag,words,0)){
                    return true;
                }
            }
        }
        return false;
    }

    public boolean dfs(char[][] board,int i,int j,int[][] flag,char[] word,int k){
        if (i<0||j<0||i>=board.length||j>=board[0].length||flag[i][j]==1||board[i][j]!=word[k]){
            return false;
        }
        if (k==word.length-1){
            return true;
        }
        flag[i][j]=1;
        if (dfs(board,i+1,j,flag,word,k+1)||dfs(board,i-1,j,flag,word,k+1)||
             dfs(board,i,j+1,flag,word,k+1)||dfs(board,i,j-1,flag,word,k+1)){
            return true;
        }
        flag[i][j]=0;
        return false;
    }
}

剑指offer13:机器人的运动范围

地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

解题思路

递归,一把梭!

代码实现

class Solution {
    int count=0;
    public int movingCount(int m, int n, int k) {
        int[][] flag=new int[m][n];
        search(flag,0,0,m-1,n-1,k);
        return count;
    }
    public void search(int[][] flag,int i,int j,int m,int n,int k){
        if (i<=m&&j<=n&&flag[i][j]!=1&&(indexSum(i)+indexSum(j))<=k){
            count++;
            flag[i][j]=1;
            search(flag,i+1,j,m,n,k);
            search(flag,i,j+1,m,n,k);
        }
    }
    public int indexSum(int n){
        int sum=n%10;
        int tmp=n/10;
        while (tmp>0){
            sum+=tmp%10;
            tmp/=10;
        }
        return sum;
    }
}

总结

本题来源于Leetcode中 归属于数组类型题目。
同许多在算法道路上不断前行的人一样,不断练习,修炼自己!
如有博客中存在的疑问或者建议,可以在下方留言一起交流,感谢各位!

觉得本博客有用的客官,可以给个赞鼓励下! 嘿嘿

喜欢本系列博客的可以关注下,以后除了会继续更新面试手撕代码文章外,还会出其他系列的文章!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值