这题有两种解法:用quicksort的partition或双指针。
Partition法:可以减少swap的次数,但不能维持数组元素的相邻顺序。 正是因为partition的这个原因,所以quicksort不是稳定排序。
代码下次补充。
双指针法: swap的次数较多,可以维持数组元素的相邻顺序。
void moveZeroes(vector<int> &nums) {
int p1=0, p2=0;
while(p2<nums.size()) {
if (nums[p2]) {
swap(nums[p1++], nums[p2]);
}
p2++;
}
}
注意:
1)对于双指针法,我的理解是,0越多,交换次数越少。
所以,对于0很少的情况,可以先预处理把非零元素复制到前部,然后把后面的元素清零。代码如下(参考了九章的讨论):
public void moveZeroes(int[] nums) {
int i = 0;
for (int j = 0; j < nums.length; j++) {
if (nums[j] != 0) {
nums[i++] = nums[j];
}
}
while (i < nums.length) {
nums[i++] = 0;
}
}
对于0很多的情况,就可以直接用上面的双指针法了,因为只需要一个循环。
解法2:很臃肿,不如上面的解法。
class Solution {
public:
/**
* @param nums: an integer array
* @return: nothing
*/
void moveZeroes(vector<int> &nums) {
int n = nums.size();
if (n == 0) return;
int left = 0, right = 0;
bool foundZero = false;
int countZero = 0;
while (right < n) {
while (right < n && nums[right] == 0) {
foundZero = true;
countZero++;
right++;
}
if (foundZero) {
nums[left] = nums[right];
}
left++;
right++;
}
for (int i = 1; i <= countZero; i++) {
nums[n - i] = 0;
}
return;
}
};
下面这个也可以,但还是不如最开始的swap的解法
class Solution {
public:
/**
* @param nums: an integer array
* @return: nothing
*/
void moveZeroes(vector<int> &nums) {
int n = nums.size();
int left = 0, right = 0;
while (right < n) {
if (nums[right] != 0) {
nums[left] = nums[right];
left++;
}
right++;
}
for (int i = left; i < n; i++) nums[i] = 0;
return;
}
};
又写了一个,好像还可以。感觉效率比一开始的那个频繁swap的版本高一点。
class Solution {
public:
/**
* @param nums: an integer array
* @return: nothing
*/
void moveZeroes(vector<int> &nums) {
int left = 0, right = 0;
while (right < nums.size()) {
if (nums[left]!= 0) left++;
else if (0 != nums[right]) {
swap(nums[left], nums[right]);
left++;
}
right++;
}
}
};