Lintcode-521: Remove Duplicate Numbers in Array (双指针经典题)

题目要求:
Do it in O(n) time complexity.
Do it in O(nlogn) time without extra space.

解法1:用unordered_set。O(n)复杂度。
注意:

  1. 这里是反向双指针。
  2. 若i对应元素已经存在于set中,则将j和i元素对调。j–。这里如果j对应元素也已经存在也没关系,因为while()又会继续检查i对应元素的。
    int deduplication(vector<int> &nums) {
        unordered_set<int> s;
        int i=0, j=nums.size()-1;
        int count=0;        
        while(i<=j) {  //注意这里是i<=j
            if (s.count(nums[i])!=0) {
                int temp=nums[i];
                nums[i]=nums[j];
                nums[j]=temp;
                count++;
                j--;
            }
            else {
                s.insert(nums[i]);
                i++;
            }
        }
        return nums.size()-count;
    }

解法2:类似解法1。也是O(n)复杂度。
注意:

  1. 这里是反向双指针
  2. 和解法1不同的是这里p1和p2都动。先看p1的元素是否已存在于set中,若否,则加入set,否则看p2的元素是不是已经存在于set中。若是,则while()循环p–,直到直到p2的元素是一个新元素或p2<p1为止。若p1<p2,则将p2元素加入set,同时p1和p2元素交换。
class Solution {
public:
    /**
     * @param nums: an array of integers
     * @return: the number of unique integers
     */
    int deduplication(vector<int> &nums) {
        int n = nums.size();
        if (n <= 1) return n;
        unordered_set<int> us;
        int count = 0;
        int p1 = 0, p2 = n - 1;
        while(p1 <= p2) {
            
            if (us.find(nums[p1]) == us.end()) {
                us.insert(nums[p1]);
                count++;
                p1++;
            } else {
                while(us.find(nums[p2]) != us.end() && (p1 <= p2)) {
                    p2--;
                }
                if (p1 < p2) {
                    us.insert(nums[p2]);
                    swap(nums[p1], nums[p2]);
                    count++;
                    p1++; p2--;
                }
            }
        }
    
        return count;
    }
};

解法3:先统统往unordered_set里面丢,最后遍历它,放到num[]开头即可。
这里不需要用到双指针,但要走2次循环。

int deduplication(vector<int> &nums) {
    unordered_set<int> s;
    for (int i=0; i<nums.size(); ++i)
        s.insert(nums[i]);
            
    int index=0;
    for (auto i : s)
        nums[index++]=i;
    return index;    
}

解法4:**排序后用双指针。一个快指针一直往前走,慢指针先不动。当快指针发现它指向的数和慢指针不一样,就把该数丢给慢指针的后一个位置。慢指针++。最后返回慢指针的值+1。**这个思路很不错。
注意这里是同向双指针!

int deduplication(vector<int> &nums) {
   if (nums.size()==0) return 0;
   sort(nums.begin(), nums.end());
   int i=0, j=0;
   while(i<nums.size()) {
       if (nums[i]!=nums[j]) {
           nums[++j]=nums[i];
       }    
       ++i;
   }
   return j+1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值