版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38371360/article/details/86529337
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:
- 必须在原数组上操作,不能拷贝额外的数组。
- 尽量减少操作次数。
思路1:
开辟一个新的空间 vector<int> nonZeroElements存放数组中所有非零的值,然后将其赋值给nums向量,最后将其他位置赋值为0。此思路时间复杂度和空间复杂度均为O(n)
class Solution {
public:
//时间复杂度:O(n)
//空间复杂度:O(n)
void moveZeroes(vector<int>& nums) {
vector<int> nonZeroElements;
for (int i = 0; i < nums.size(); i++)
if (nums[i])
nonZeroElements.push_back(nums[i]);
for (int i = 0; i < nonZeroElements.size(); i++)
nums[i] = nonZeroElements[i];
for (int i = nonZeroElements.size(); i < nums.size(); i++)
nums[i] = 0;
}
};
LeetCode上运行通过,时间为20ms,仅战胜38.46%的cpp提交者。
思路2:
减少空间复杂度,不在开辟新的空间,设置一个向量k,通过改变k的值使得nums中[0,k)的元素均为非零元素。
此思路的时间复杂度为O(n),空间复杂度为O(1)
class Solution {
public:
//时间复杂度:O(n)
//空间复杂度:O(1)
void moveZeroes(vector<int>& nums) {
int k = 0; // 在nums中,[0...k)的元素均为非0元素
// 遍历到第i个元素后,保证[0...i]中所有非0元素全都按照顺序排列在[0...k)的空间中
for (int i = 0; i < nums.size(); i++)
if (nums[i])
nums[k++] = nums[i];//首先nums[k] = nums[i] ; 在k++
//将nums剩余位置都放置为0
for (int i = k; i < nums.size(); i++)
nums[i] = 0;
}
};
时间缩短成了12ms,战胜了98.77%的cpp提交记录。
思路3:
能不能 仅仅在nums内部进行两两比较来交换值。
此思路时间复杂度为O(n),空间复杂度为(1)
class Solution {
public:
//时间复杂度:O(n)
//空间复杂度:O(1)
void moveZeroes(vector<int>& nums) {
int k = 0; // 在nums中,[0...k)的元素均为非0元素
// 遍历到第i个元素后,保证[0...i]中所有非0元素全都按照顺序排列在[0...k)的空间中,同时[k...i]为0
for (int i = 0; i < nums.size(); i++)
if (nums[i])
swap(nums[k++], nums[i]);
}
};
思路4:
思路3中的交换值未考虑一种特殊情况,即如果此向量大部分都是非零数字的话,就可以出现非零元素自己和自己交换,这块的代码可以进行优化,增加一个判断条件。
class Solution {
public:
//时间复杂度:O(n)
//空间复杂度:O(1)
void moveZeroes(vector<int>& nums) {
int k = 0; // 在nums中,[0...k)的元素均为非0元素
// 遍历到第i个元素后,保证[0...i]中所有非0元素全都按照顺序排列在[0...k)的空间中,同时[k...i]为0
for (int i = 0; i < nums.size(); i++)
if (nums[i])
if (i != k) //特殊情况是如果全部都是非零数字的话,那样就会出现非零元素自己和自己交换。那么main_3的算法就需要优化。
swap(nums[k++], nums[i]);
else
k++;
}
};
思路2、3、4的运行时间均为12ms,但是思路4的方法考虑的最全面。