数组的改变、移动
力扣题目编号,数组的改变、移动:453、665、283
453: 最小移动次数使数组元素相等
给定一个长度为 n 的非空整数数组,找到让数组所有元素相等的最小移动次数。每次移动将会使 n - 1 个元素增加 1。
示例:
输入:[1,2,3]
输出:3
解释:
只需要3次移动(注意每次移动会增加两个元素的值):
[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]
解题思路
分析题目,每次移动将会使 n - 1 个元素增加 1,可以反向理解,每次就有一个元素-1。
例:
[1,2,3]=>[1,2,2]=>[1,2,1]=>[1,1,1]。
[1,2,3,4]=>[1,2,3,3]=>[1,2,3,2]=>[1,2,2,2]=>[1,1,2,2]=>[1,1,1,2]=>[1,1,1,1]
这样就很好理解了,所有的元素都在向最小的元素靠近,每一次只有一个元素减1。
所以我们需要先找到数组中最小的元素,并使所有的元素减去它,并累加。
实现代码
class Solution {
public:
int minMoves(vector<int>& nums) {
int n = nums.size();
int res = 0;
int min = INT_MAX;
for(int i = 0 ; i < n ;i++ ){
if(nums[i]<min){
min=nums[i];
}
}
for(int j = 0 ; j < n ; j ++){
res = res + nums[j] - min;
}
return res;
}
};
665:非递减数列
给你一个长度为 n 的整数数组,请你判断在 最多 改变 1 个元素的情况下,该数组能否变成一个非递减数列。
我们是这样定义一个非递减数列的: 对于数组中所有的 i (0 <= i <= n-2),总满足 nums[i] <= nums[i + 1]。
示例 1:
输入: nums = [4,2,3]
输出: true
解释: 你可以通过把第一个4变成1来使得它成为一个非递减数列。
示例 2:
输入: nums = [4,2,1]
输出: false
解释: 你不能在只改变一个元素的情况下将其变为非递减数列。
说明:
- 1 <= n <= 10 ^ 4
- 10 ^ 5 <= nums[i] <= 10 ^ 5
解题思路
看大佬的解题思路:
作者:johnlee1
这道题可以看做是找向下拐点的过程,如果向下拐点存在,那么你就需要作出改变数字的操作了
根据题意,非递减序列可以看做一个非单调的递增序列,那么我们改变向下拐点的方法也就有两种:
下移
上移
如何确定是哪一种,就需要向下拐点的前一个元素来帮忙了。
显然,如果在拐点前一位元素<拐点后一位元素时,选择向上移的方法就有可能存在拐点没有被消除的现象,而如果选择向下移,就可以完全避免这种情况:
如果前一位元素≥后一位元素,就只能采用上移才能保证向下拐点消除:
操作一次计数器增加1,当出现第二个向下拐点时,就说明改变一次是不行滴,返回false。
实现代码
class Solution {
public:
bool checkPossibility(vector<int>& nums) {
int sum=0;
for(int i=1;i<nums.size();i++){
if(nums[i-1]>nums[i]){
sum++;
if(sum>=2) return false;
if(i-2>=0 && nums[i-2]>nums[i]){
nums[i]=nums[i-1];
}
else nums[i-1]=nums[i];
}
}
return true;
}
};
283:移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:
1.必须在原数组上操作,不能拷贝额外的数组。
2.尽量减少操作次数。
解题思路
两种解法。
①:定义一个为0的变量,遍历数组找到不为0的元素,把它赋值为nums[count],每赋值一次count++。直到遍历结束。
数组遍历结束后,count的值小于或等于数组的长度,所以我们需要对count以后的元素进行赋值为0。
②:使用类似冒泡排序的算法,利用双重循环,第二层循环在碰到非零元素的时候,进行交换并break;
原数组 | [0,0,1,2,3] |
---|---|
循环一次 | [1,0,0,2,3] |
循环二次 | [1,2,0,0,3] |
循环三次 | [1,2,3,0,0] |
实现代码
①
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int count = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] != 0) {
nums[count++] = nums[i];
}
}
for (int i = count; i < nums.size(); i++) {
nums[i] = 0;
}
}
};
②
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int n = nums.size();
for(int i = 0 ; i < n ; i++){
if(nums[i]==0){
for(int j = i+1 ; j < n ; j ++){
if(nums[j]!=0){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
break;
}
}
}
}
}
};