1.题意解析
题目特别强调了要原地操作。这就说明本地不能开辟新数组来辅助解题。
如果排除这个条件的话,按照一般的思维,就是开辟一个新数组,对原数组进行遍历,找到非零元素,赋值到新数组中,遍历完后就在新数组后补零。
现在就是要考虑,如何将这些操作压缩在同一个数组中完成。
2.解法一
按照上面的思路,我们可以定义两个指针:first和second。
- first:first指针用于遍历数组,找出非0元素。
- secod:将找到的非零元素,赋值到second指针处,之后second指针前进一位。
遍历完之后,second指针前一位就指向了最后一个非0元素。此时从second指针开始,所有位置补0。
具体代码如下:
public void moveZeroes(int[] nums) {
int second = 0;
for (int first = 0; first < nums.length; first++) {
if (nums[first] != 0) {
nums[second++] = nums[first];
}
}
for (int i = second; i < nums.length; i++) {
nums[i] = 0;
}
}
3.解法二
上面的解法被拆成了两部分,先是将非0元素挪到数组前面,再在其后面补0。
但我们可以换种思路:
同样是定义两个指针:first和second。
- first:first指针同样是找出非0元素。
- second:second指针表示当前非0元素要交换的位置。在找出非0元素后,将其和second指针的元素交换,交换后second指针前进一位。
这就相当于,每次找出非0元素,就把它放到数组前面位置。随着first指针的遍历,最终所有非0元素都放在数组前面,后面一定全是0。
具体代码如下:
public void moveZeroes(int[] nums) {
int second = 0;
for (int first = 0; first < nums.length; first++) {
if (nums[first] != 0) {
// 交换first指针元素和second指针元素的位置
int temp = nums[first];
nums[first] = nums[second];
nums[second] = temp;
// second前移1位,表示下一个非0元素要放的位置
second++;
}
}
}
4.总结
两种解法都用到了双指针,差别在于second指针所代表的含义。通常遇到原地操作的数组题目,一般用双指针都能解出来。