453. 最小操作次数使数组元素相等

思路

将除了一个元素之外的全部元素+1,等价于将该元素-1,因为我们只对元素的相对大小感兴趣。因此,该问题简化为需要进行的减法次数。

代码

  1. /**
  2. * @param {number[]} nums
  3. * @return {number}
  4. */
  5. var minMoves = function(nums) {
  6. let ret = 0, min = Number.MAX_SAFE_INTEGER;
  7. for(let i = 0; i < nums.length; i ++) {
  8. min = Math.min(min, nums[i]);
  9. }
  10. for(let i = 0; i < nums.length; i ++) {
  11. ret += nums[i] - min;
  12. }
  13. return ret;
  14. };

复杂度分析

时间复杂度 数组的改变、移动 - 图1#card=math&code=O%28N%29)
空间复杂度 数组的改变、移动 - 图2#card=math&code=O%281%29)

665. 非递减数列

思路

当 nums[i] 破坏了数组的单调递增时,即 nums[i] < nums[i - 1] 时,为了让数组有序,发现一个规律(在上面三个例子中, nums[i] 都为 2, nums[i -1] 都为 4):

①4, 2, 5,当 i = 1 ,那么修改 num[i- 1] ,不要动 nums[i] ,因为nums[i]后面的元素是啥我们还不知道呢,少动它为妙。
②1, 4, 2, 5,当 i > 1 时,我们应该优先考虑把 nums[i - 1] 调小到 >= nums[i - 2] 并且 <= nums[i]。同样尽量不去修改 nums[i] ,理由同上。
③3, 4, 2, 5,当 i > 1 且 nums[i] < nums[i - 2] 时,我们无法调整 nums[i - 1] ,我们只能调整 nums[i] 到 nums[i - 1] 。

代码

  1. /**
  2. * @param {number[]} nums
  3. * @return {boolean}
  4. */
  5. var checkPossibility = function(nums) {
  6. let ret = 0, len = nums.length;
  7. for(let i = 1; i < len; i++) {
  8. if (nums[i] < nums[i - 1]) {
  9. ret += 1
  10. if (i == 1 || nums[i] >= nums[i - 2])
  11. nums[i - 1] = nums[i]
  12. else
  13. nums[i] = nums[i - 1]
  14. }
  15. }
  16. return ret <= 1
  17. };

复杂度分析

时间复杂度 数组的改变、移动 - 图3#card=math&code=O%28N%29)
空间复杂度 数组的改变、移动 - 图4#card=math&code=O%281%29)

283. 移动零

思路

利用双指针

  1. 如果左右指针都为0,则将右指针右移
  2. 如果左指针为0,则交换指针对应的值

代码

  1. var moveZeroes = function(nums) {
  2. let len = nums.length, left = 0, right = 1;
  3. while(left < right && right < len) {
  4. if (!nums[left] && !nums[right]) {
  5. right ++
  6. continue
  7. }
  8. if (!nums[left]) {
  9. [nums[left], nums[right]] = [nums[right], nums[left]]
  10. }
  11. left ++
  12. right ++
  13. }
  14. return nums
  15. };

复杂度分析

时间复杂度 数组的改变、移动 - 图5#card=math&code=O%28N%29)
空间复杂度 数组的改变、移动 - 图6#card=math&code=O%281%29)