快慢指针-删除数组元素

有序删重复

删除有序数组中的重复项:每个元素只出现一次

题目链接
思路:快慢指针

让慢指针slow走在后面,快指针fast走在前面探路,找到一个不重复的元素就告诉slow,slow前进一步并接收fast指向的元素。

这样当fast指针遍历完整个数组nums后,nums[0..slow]就是所有数组中的所有元素且仅出现一次。

关键点:
1、是先slow++,还是先 nums[slow]=nums[fast]; 这个需要判断
2、fast在什么时候停下来做判断

class Solution {
    public int removeDuplicates(int[] nums) {
        int n=nums.length;
        if(n<2){
            return n;
        }
        int slow=0,fast=0;
        while (fast<n){
            if(nums[slow]!=nums[fast]){
                slow++;
                nums[slow]=nums[fast];
            }
            fast++;
        }
        return slow+1;
    }
}

删除有序数组中的重复项 II:每个元素最多出现k次

添加链接描述
题目要求保留两个,其实任意多个都是可以的,所以下面写通用解法,对于本题就是k=2;

//解法自己想到的nice
class Solution {
    public int removeDuplicates(int[] nums) {
        int k=2;
        int n=nums.length;
        if(n<3){
            return n;
        }
        int i=0,slow=0,fast=0;
        while (fast<n){
            while (fast<n && nums[fast]==nums[slow]) fast++;
            int len=fast-slow;
            len=Math.min(len,k);
            while (len>0){
                nums[i++]=nums[slow];
                len--;
            }
            slow=fast;
        }

        return i; //返回i不是slow
    }
}

删除有序链表中的重复项:每个元素只出现一次

题目链接
其实和数组是一模一样的,唯一的区别是把数组赋值操作变成操作指针而已

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if(head==null || head.next==null){
            return head;
        }

        //养成好习惯,无论head会不会改变
        ListNode preNode=new ListNode(0);
        preNode.next=head;
        
        ListNode slow=head;
        ListNode fast=head.next;

        while (fast!=null){
            if(slow.val!=fast.val){
                slow.next=fast;
                slow=fast;
            }
            fast=fast.next;
        }
        //特殊情况:末尾节点有重复
        slow.next=null;
        return preNode.next;
    }
}

删除有序链表中的重复项:一个也不留

添加链接描述
写法有很多,下面这种相对更符合自己的思维

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode pre = new ListNode(0);
        pre.next = head;
        ListNode p = pre;
        ListNode slow = head;
        ListNode fast = head.next;
        while (fast != null) {
            if (slow.val == fast.val) {
                while (fast != null && slow.val == fast.val) fast = fast.next;
                p.next = fast;
                if (fast == null) {
                    return pre.next;
                }
            } else {
                p = slow;
            }
            slow = fast;
            fast = fast.next;
        }
        return pre.next;
    }
}

删除无序数组中的目标值

题目链接

class Solution {
    public int removeElement(int[] nums, int val) {
        int slow=0,fast=0;
        while (fast<nums.length){
            if(nums[fast]!=val){
                nums[slow]=nums[fast]; //先覆盖再slow++
                slow++;
            }
            fast++;
        }

        return slow;

    }
}

移动0

题目链接
思路:题目要求移动0,可以转换思路,不一定非要移动,可以删除0,然后再后面补0即可。于是就变成了上题“移除元素”中val看做0即可。

代码:

class Solution {
    public void moveZeroes(int[] nums) {
        int slow=0,fast=0;
        while (fast<nums.length){
            if(nums[fast]!=0){
                nums[slow]=nums[fast];
                slow++;
            }
            fast++;
        }

// 注意不要用while循环,因为会超时。
        for (int i=slow;i<nums.length;i++){
            nums[i]=0;
        }

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值