题目:Move Zeroes
描述:
Given an array nums, write a function to move all 0’s to the end of it while maintaining the relative order of the non-zero elements.
For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0, 0].
Note:
1、You must do this in-place without making a copy of the array.
2、Minimize the total number of operations.
翻译:
将数组中的所有0移动到末尾,并保持非0元素的顺序不改变。
比如[0,1,0,3,12]移动后的期望数组为[1,3,12,0,0]
小要求:
1、不能创建一个新的数组来做操作
2、尽量少的操作次数
答案:
public void moveZeroes(int[] nums) {
int size = nums.length;
int startIndex = 0;
// 0元素开始的位置
int endIndex = 0;
// 0元素结束的位置
int currentNum;
int i= 0;
// 第一步:找到第一个0元素开始的位置
// 并将第一个0元素的游标赋值给startIndex&endIndex
while(i < size){
currentNum = nums[i];
if (currentNum == 0) {
startIndex = i;
endIndex = i;
break;
}
++i;
}
// 如果当前数组中没有找到0元素,则推出
if (nums[endIndex] != 0)
return;
// 将当前i的值加1;直接从刚才0元素位置的后一位置开始循环
++i;
while (i < size) {
currentNum = nums[i];
if (currentNum == 0){//如果当前元素等于0,则将i值赋值给endIndex
endIndex = i;
} else {
// 如果不为0
//则将当前元素赋值给nums[startIndex]
// 并将当前位置的元素赋值为0
// startIndex和endIndex都加1;
nums[startIndex] = currentNum;
nums[i] = 0;
++startIndex;
++endIndex;
}
++i;
}
}
算法解释
此算法的精髓在于:在循环遍历中将0元素全部集中起来,整体向后移位,但是由于连续的0元素都是相等的,因此就算往前移位,也只需要将最前面的0元素和连续0元素的结束位置的后一位元素进行调换,相当于整个0元素块都向后移动了一位。
由于数组中可能有多个0,因此,第一次循环的时候,就将第一个0元素找出,并且记录当前0元素的游标(此时0元素开始的游标和结束的游标相等),第二次循环的时候,直接从0元素结束的游标的后一位开始循环遍历,如果循环遍历过程中,遇到了0元素,则将0元素的结束游标+1;如果没有遇到0元素,则将0元素开始位置和当前位置的数进行置换,并且将0元素的开始游标和结束游标都+1。