LeetCode26、27 删重复元素

本文介绍了解决LeetCode26题目的一种算法实现方法。该方法通过双指针技巧,在原地修改输入数组并仅使用O(1)额外空间条件下,有效删除排序数组中的重复元素,确保每个元素仅出现一次,并返回新数组的长度。

LeetCode26 删重复元素

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定数组 nums = [1,1,2],

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。

你不需要考虑数组中超出新长度后面的元素。

思路

考虑用 2 个指针,一个在前记作 p,一个在后记作 q,算法流程如下:

1.比较 p 和 q 位置的元素是否相等。

如果相等,q 后移 1 位
如果不相等,将 q 位置的元素复制到 p+1 位置上,p 后移一位,q 后移 1 位
重复上述过程,直到 q 等于数组长度。

返回 p + 1,即为新数组长度。

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

第27题类似,只用改一个比较的地方

 class Solution {
    public int removeElement(int[] nums, int val) {
        if(nums==null)return 0;
        int p=0,q=0;
        while(q<nums.length){
            if(nums[q]!=val){
                nums[p]=nums[q];
                p++;
            }q++;
        }
        return p;
    }
}

LeetCode 中有如除排序链表中的重复元素 II、除排序数组中的重复项 II 等除元素 II 相关题目,以下为对应的解决方案: ### 除排序链表中的重复元素 II #### 递归解法 ```cpp /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* deleteDuplicates(ListNode* head) { if(!head || !head->next) return head; ListNode* p = head->next; if(head->val == p->val) //把有重复的全了,返回deleteDuplicates(p) { while(p && p->val == head->val) { ListNode* tmp = p; p = p->next; delete tmp; } delete head; return deleteDuplicates(p); } else { head->next = deleteDuplicates(head->next); return head; } } }; ``` 该解法通过递归的方式处理链表,若当前节点与下一个节点值相同,则除所有重复节点并递归处理后续节点;若不同,则递归处理当前节点的下一个节点并返回当前节点[^1]。 #### 非递归解法 ```cpp class Solution { public: void action(int &num, ListNode *&header, ListNode *&tail, ListNode *&last, ListNode *&node) { if (num > 1) { num = 1; last = node; return; } // 需要插入,则先插入,然后添加记录新节点 if (header == nullptr) { header = last; tail = last; } else { tail->next = last; tail = last; } if (node == nullptr) { return; } num = 1; last = node; tail->next = nullptr; } ListNode *deleteDuplicates(ListNode *head) { int num = 0; // 头节点 ListNode *header = nullptr; // 筛选后的节点后最后一个 ListNode *tail = nullptr; // 最后一个记录的节点 ListNode *last = nullptr; while (head != nullptr) { ListNode *node = head; head = head->next; // 第一个节点时 if (last == nullptr) { num = 1; last = node; continue; } // 当前节点和上一个节点是一样的 if (node->val == last->val) { num++; continue; } // 不一样,则判断是需要插入,还是抛弃,num>1是抛弃 action(num, header, tail, last, node); } ListNode *end = nullptr; action(num, header, tail, last, end); return header; } }; ``` 此解法使用循环遍历链表,借助多个指针和一个计数器,根据相邻节点值是否相等来决定是否除重复节点,最终返回处理后的链表头节点[^4]。 ### 除排序数组中的重复项 II ```cpp class Solution { public: int removeDuplicates(vector<int>& nums) { if(nums.size() <= 2) return nums.size(); int index = 2; for(int i = 2; i < nums.size(); i++)//从第三个数开始考虑 { if(nums[i] != nums[index - 2]) nums[index++] = nums[i]; } return index; } }; ``` 该解法使用一个变量记录满足条件的元素个数,从数组的第三个元素开始遍历,若当前元素与前两个元素不同,则将其放到记录位置并更新记录位置,最终返回满足条件的元素个数[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值