剑指offer之数组(3)

47. 礼物的最大价值 难度:中等

本题典型的动态规划问题,我们创建一个二维数组dp来记录对grid数组遍历到的每一位的礼物的最大价值,值得一提的是我们创建的dp数组的行列都比grid数组多1,这是为了解决边界问题。

class Solution {
    
    
    public int maxValue(int[][] grid) {
    
    
        int row = grid.length;
        int col = grid[0].length;
        int[][] dp = new int[row+1][col+1];
        for(int i = 1;i<=row;++i){
    
    
            for(int j = 1;j<=col;++j){
    
    
                dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1])+grid[i-1][j-1];
            }
        }
        return dp[row][col];
    }
}

63. 股票的最大利润 难度:中等

本题也是典型的动态规划问题,我们创建两个变量:cost用来记录当前遍历到的价格中最小价格;profit用来记录当前的最大利润,那么遍历一遍数组即可得到最大利润。

class Solution {
    
    
    public int maxProfit(int[] prices) {
    
    
        int cost = Integer.MAX_VALUE;
        int profit = 0;
        for(int price:prices){
    
    
            cost = Math.min(cost,price);
            profit = Math.max(profit,price-cost);
        }
        return profit;
    }
}

53. 在排序数组中查找数字-I 难度:简单

在排序数组中查找数字首选二分查找。问题是我们要得到该数字在数组中出现的次数,解决方法是:在初次找到该数字时,我们将左右指针移到该数字下标,再分别往两边走,直到下标所指数字不等于该数字时,指针相减再减一即可。

class Solution {
    
    
    public int search(int[] nums, int target) {
    
    
        int l = 0;
        int r = nums.length-1;
        int mid = (l+r)/2;
        int res = 0;
        while(l <= r){
    
    
            if(nums[mid] > target){
    
    
                r=mid-1;
                mid=(l+r)/2;
            }
            else if(nums[mid] < target){
    
    
                l = mid+1;
                mid=(l+r)/2;
            }else{
    
    
                l=mid;
                r=mid;
                while(l>=0 && nums[l] == target)  l--;
                while(r<nums.length && nums[r] == target)  r++;
                res = r-l-1;
                return res;
            }
        }
        return res;
    }
}

53. 在排序数组中查找数字-II 难度:简单

本题数组长度为n,而且数组中所有数字的大小都在0~n之内,但是0 ~ n是n+1个数,由于数组长度为n,那么必定有一个数不存在,我们就是要找到这个数。

排序数组中的查找,首选二分查找。根据题目描述,该数组下标与其对应的数应该是相等的关系,当我们遇到下标与其对应的数不等的情况时,该数组下标就是我们要找的数。

class Solution {
    
    
    public int missingNumber(int[] nums) {
    
    
        int l = 0, r = nums.length-1;
        while(l <= r){
    
    
            int mid = (l+r)/2;
            if(nums[mid] == mid)    l=mid+1;
            else    r = mid-1;
        }
        return l;
    }
}

61. 扑克牌中的顺子 难度:简单

本题在于判断五张牌是否是一个顺子,那么我们将所有不是顺子的情况一一列举出来就可以了:

1.五张牌中存在除0以外任意相同的牌

2.五张牌中最大的牌与最小的牌相差大于等于5

所以本题用Set集合来储存非0的牌再加以判断即可。

class Solution {
    
    
    public boolean isStraight(int[] nums) {
    
    
        Set<Integer>  set = new HashSet<>();
        int max = -1,min = 14;
        for(int n:nums){
    
    
            if(n == 0)  continue;
            max = Math.max(max,n);
            min = Math.min(min,n);
            if(max - min >=5)   return false;
            if(set.contains(n)) return false;
            set.add(n);
        }
        return true;
    }
}

66. 构建乘积数组 难度:中等

本题的难点在于不能用除法,那么我们可以通过矩阵的上三角和下三角来计算乘积,正对角线中的元素全为1,代表本位乘1,下三角直接计算即可,上三角需要用tmp来储存临时结果,再代入计算。

class Solution {
    
    
    public int[] constructArr(int[] a) {
    
    
        int len = a.length;
        if(len == 0)   return new int[0];
        int[] b = new int[len];
        int tmp = 1;
        b[0] = 1;
        for(int i = 1;i<len;++i){
    
    
            b[i] = b[i-1]*a[i-1];
        }
        for(int i = len-2;i>=0;--i){
    
    
            tmp *= a[i+1];
            b[i] *=tmp;
        }
        return b;
    }
}

代码参考LeetCode作者:Krahets

猜你喜欢

转载自blog.csdn.net/m0_52373742/article/details/121160231