数组题目: 665. 非递减数列、453. 最小移动次数使数组元素相等、283. 移动零、189. 旋转数组、396. 旋转函数

665. 非递减数列

题解:

题目要求一个非递减数列,我们可以考虑需要更改的情况:

  • nums = {4, 2, 5}

对于这个nums,由于2的出现导致非递减,更改的情况就是要么4调到<=2,要么2调到4,5.

  • nums = {1, 4, 2, 5}

对于这个nums,由于2的出现导致非递减,更改的情况就是要么4调到1,,2,要么2调到4,5.

  • nums = {3, 4, 2, 5}

对于这个nums,由于2的出现导致非递减,更改的情况就是2调到4,5.

所以算法就是:

如果按照1的情况,当i = 1,那么直接就把nums[i - 1]改成nums[i],nums[i]不动

如果按照2的情况,当nums[i - 2] < nums[i],那我们就优先考虑把nums[i - 1] 调小到 >= nums[i - 2] 并且 <= nums[i]

如果按照1的情况,nums[i - 2] > nums[i],那我们就调整nums[i],让nums[i] = nums[i - 1]。

代码:

class Solution {
    public boolean checkPossibility(int[] nums) {
        int count = 0;//统计需要满足非递减的次数
        for(int i = 1; i < nums.length;i++){
            if(nums[i] < nums[i - 1]){
                if(i == 1 || nums[i] >= nums[i - 2]){// i=1就是第一个情况,后面的是第二种
                    nums[i - 1] = nums[i];
                }else{
                    nums[i] = nums[i - 1];
                }
                count++;
            }
        }
        return count <= 1;
    }
}

453. 最小移动次数使数组元素相等

数组题目: 665. 非递减数列、453. 最小移动次数使数组元素相等、283. 移动零、189. 旋转数组、396. 旋转函数_第1张图片

思路:

题目要求我们每次操作将会让n-1个元素增加1,来满足要求。我们可以反过来思考,找到最小的数,遍历其他的数,累加所有元素和最小的元素的差距。

代码:

class Solution {
    public int minMoves(int[] nums) {
        int minNum = Arrays.stream(nums).min().getAsInt();
        int res = 0;
        for(int num : nums){
            res += num - minNum;
        }
        return res;
    }
}

283. 移动零

数组题目: 665. 非递减数列、453. 最小移动次数使数组元素相等、283. 移动零、189. 旋转数组、396. 旋转函数_第2张图片

思路:(双指针)

我们定义两个指针left, right都等于0,遍历nums,如果nums[right] != 0,那我们就让nums[left]和nums[right]进行交换,再把Left增加。如果等于0,那就让right++。

其实Left就是第一个0的位置,right就是让他找到不为0的地方。

数组题目: 665. 非递减数列、453. 最小移动次数使数组元素相等、283. 移动零、189. 旋转数组、396. 旋转函数_第3张图片


189. 旋转数组

思路:

  • 第一步:先翻转数组里的数
  • 第二步:翻转前[0, k - 1]个数
  • 第三步:翻转后面[k, n]的数

数组题目: 665. 非递减数列、453. 最小移动次数使数组元素相等、283. 移动零、189. 旋转数组、396. 旋转函数_第4张图片

代码:

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

    public void reverse(int[] nums, int left, int right){
        while(left <= right){
            int temp = nums[left];
            nums[left] = nums[right];
            nums[right] = temp;
            left++;
            right--;
        }
    }
}

396. 旋转函数

数组题目: 665. 非递减数列、453. 最小移动次数使数组元素相等、283. 移动零、189. 旋转数组、396. 旋转函数_第5张图片

思路:

找规律

数组题目: 665. 非递减数列、453. 最小移动次数使数组元素相等、283. 移动零、189. 旋转数组、396. 旋转函数_第6张图片

所以对应的公式:

F[i] = F[i - 1] + sum - n * nums[n - i];

代码:

class Solution {
    public int maxRotateFunction(int[] nums) {
        int sum = 0, f = 0, n = nums.length, ans = 0;
        for(int i = 0; i < n; i++){
            sum += nums[i];
            f += i * nums[i];//f(0);
        }
        ans = f;
        for(int i = 1; i < n; i++){
            f = f + sum - n * (nums[n - i]);//f[i] = f[i - 1] + sum -n * nums[n - i];
            ans = Math.max(ans, f);
        }
        return ans;
    }
}

你可能感兴趣的:(数组,算法)