1.移动零
1.1我的方法
刚开始读错题目,认为非零元素的相对顺序是按大小排序,解法一并附上,感兴趣可自行阅读
int count = 0;//记录0的个数
for (int num : nums) {
//先对数组中0的个数进行记录
if (num == 0) {
count++;
}
}
boolean flag = false;//移位标记
for (int i = 0; i < nums.length; i++) {
if(i+1!=nums.length&&!flag&&nums[i]==0&&nums[i+1]!=0){
//说明为连续0的最后一个0,可以开始移位
flag = true;
continue;//当前循环不进行移位
}
if(flag){
//可以开始移位
nums[i-count]=nums[i];
}
}
//最后将数组后count个元素赋值为0
for (int i = count; i != 0; i--) {
nums[nums.length-i]=0;
}
以下为正确题解:
TreeSet<Integer> set = new TreeSet<>();
for (int i = 0; i < nums.length; i++) {
if(nums[i]==0){
//如果当前元素是0,与后方第一个不为0的元素交换顺序
set.add(i);//先记录下0元素的索引
}
if(!set.isEmpty() &&nums[i]!=0){
//如果set中已经记录多个,从最小的开始交换
nums[set.first()]=nums[i];
nums[i]=0;
set.remove(set.first());
set.add(i);//当前元素变为0,加入set
}
}
思路:使用TreeSet来保存0元素的索引,遍历数组,如果当前元素为0,加入set进行处理,如果元素不是0,判断set中是否有需要处理的0元素,如果有,交换索引最小的0元素和当前元素的顺序,则当前元素变为0,加入set中
1.2双指针法
public void moveZeroes(int[] nums) {
int slow = 0; // 慢指针:下一个非零元素的写入位置
for (int fast = 0; fast < nums.length; fast++) {
if (nums[fast] != 0) {
// 将非零元素移到慢指针位置(只操作非零元素)
nums[slow] = nums[fast];
// 如果位置不同,将原位置设为0(避免覆盖非零数据)
if (slow != fast) {
nums[fast] = 0;
}
slow++; // 慢指针后移
}
}
}
思路:定义快慢指针指向第一个元素,慢指针遇到0元素停下,快指针遇到非0元素就和慢指针的元素交换