LeetCode26/27/80/75 Remove Duplicates from Sorted Array I and II/Remove Element/Set Colors**

一:Remove Duplicates from Sorted Array

题目:

Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.

Do not allocate extra space for another array, you must do this in place with constant memory.

For example,
Given input array A = [1,1,2],

Your function should return length = 2, and A is now [1,2].

链接:https://leetcode.com/problems/remove-duplicates-from-sorted-array/

分析:这道题很简单,就是移除有序数组中重复的元素,这里我给出三种方法。

法一:暴力

for(int i = 0; i < n; i++){
            int j = 1;
            while((i+j)<n && A[i] == A[i+j]){
                j++;
            }
            if(j > 1){
                for(int k = i+j; k < n; k++)
                    A[k-j+1] = A[k];
                n = n-j+1;
                
            }
        }
        return n
结果是TLE,因为当元素是[-998,-998,-997,-997,-997...] 每遍历一次,都几乎需要移动O(n)次,很明显超时

法二:设了一个vector,简单多了,但是需要额外的空间,不知道怎么在leetcode上也通过了,时间复杂度为O(N),但是空间复杂度也为O(N) 不满足要求

if(n == 0) return 0;
        vector <int>v;
        v.push_back(A[0]);
        for(int i = 1; i < n; i++){
            if(A[i] != v.back()) v.push_back(A[i]);
        }
        for(int i = 0; i < v.size(); i++)
            A[i] = v[i];
        return v.size();

法三: 设置一个计算器,用来统计不重复元素个数,当元素不同时,每当遍历前后元素不相同,计数器加1,并将当前遍历的元素放入计数器对应在数组中位置。it is amazing!!!也可以说是双指针的思想!!

class Solution {
public:
    int removeDuplicates(int A[], int n) {
        // 法一:
       /* for(int i = 0; i < n; i++){
            int j = 1;
            while((i+j)<n && A[i] == A[i+j]){
                j++;
            }
            if(j > 1){
                for(int k = i+j; k < n; k++)
                    A[k-j+1] = A[k];
                n = n-j+1;
                
            }
        }
        return n;*/
        // 法二 这样也能  AC ?
        /*if(n == 0) return 0;
        vector <int>v;
        v.push_back(A[0]);
        for(int i = 1; i < n; i++){
            if(A[i] != v.back()) v.push_back(A[i]);
        }
        for(int i = 0; i < v.size(); i++)
            A[i] = v[i];
        return v.size();*/
        // 法三 It is  amazing!!
        if(n == 0) return 0;
        int index = 1;
        for(int i = 1;i < n; i++){
            if(A[i] != A[i-1]){
                A[index++] = A[i];
            }
        }
        return index;
        
    }
};

二:Remove Element

题目:

Given an array and a value, remove all instances of that value in place and return the new length.

The order of elements can be changed. It doesn't matter what you leave beyond the new length.

链接:https://leetcode.com/problems/remove-element/

分析:就是移除数组中==指定elem的元素。

方法一:先排序,后找到该元素,后通过移动进行删除,,--————麻烦复杂————O(NlgN)

sort(A, A+n);       // 排序
        int count = 0;
        int index = 0;
        for(int i = 0; i < n; i++){    // 记录==elem的元素个数及最后的下标
            if(A[i] == elem){ 
                count ++;
                index = i;
            }
        }
        for(int i = index+1; i < n; i++){     // 移动数组
            A[i-count] = A[i];
        }
        return n-count;

方法二: 计数器法,遍历一次,如果该元素不等于elem,则将该元素放入计数器所定位的位置。计数器的位置小于等于当前遍历的下标,所以不会影响后续遍历。时间复杂度为O(N).

class Solution {
public:
    int removeElement(int A[], int n, int elem) {
        int index = 0;
        for(int i = 0; i < n; i++){
            if(A[i] != elem)
                A[index++] = A[i];
        }
        return index;
        
    }
};

三: Remove Duplicates from Sorted ArrayII

题目:

Follow up for "Remove Duplicates":
What if duplicates are allowed at most twice?

For example,
Given sorted array A = [1,1,1,2,2,3],

Your function should return length = 5, and A is now [1,1,2,2,3].

链接:https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/

分析:仍然是计数器+双指针的思想

class Solution {
public:
    int removeDuplicates(int A[], int n) {
        if(n == 0 || n == 1)return n;
        int index = 1;
        for(int i = 1; i < n-1; i++){
            if(A[i] != A[i-1] || A[i] != A[i+1]){   // 通过判断前一个元素与后一个元素
                A[index++]= A[i];
            }
        }
        A[index++] = A[n-1];
        return index;
        
    }
};

四:Set Colors

题目:

Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.

Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.

Note:
You are not suppose to use the library's sort function for this problem.

链接:https://leetcode.com/problems/sort-colors/

分析:此题可以有三种解法,常规解法两遍扫描肯定可以搞定,那能不能一遍扫描搞定呢?同样是双指针的思想。。

法一:两遍扫描:设头指针为i,先从头开始找设为指针k,凡是为0的则与头指针互换,并且i++,k++,, 这样就把所有为0的调到了头部,,然后同理,从尾部扫描,把等于2的全部调到数组的尾部,这样就可以了。

/*两边扫描的方法*/
class Solution {
public:
    void sortColors(int A[], int n) {
        if(n == 0) return;
        int i = 0, j = n-1, k = 0;
        while(k <= j){
            if(A[k] == 0){
                swap(A[i], A[k]);
                i++;
            }
            k++;
        }
        k--;
        while(k >= i){
            if(A[k] == 2){
                swap(A[k], A[j]);
                j--;
            }
            k--;
        }
    }
};

法二:一遍扫描法

思路:设置头尾指针i和j,然后从头开始遍历,凡是遇到0的则与i位置互换值,并且i++,k++,遇到2则与j位置互换,此时j--,(但是没有k++,因为互换过来的值可能也为2,需要重新判断一次),为1则不管k++

/*一遍扫描*/
class Solution {
public:
    void sortColors(int A[], int n) {
        if(n == 0) return;
        int i = 0, j = n-1, k = 0;
        while(k <= j){
            if(A[k]==0 ){
                swap(A[k], A[i++]);
                k++;
            }else if(A[k]==2){ // 当A[k]==2的时候 互换后,
                swap(A[k], A[j--]);   // 不对k++(互换后A[k]有可能等于2),此时j--也一样 
            }else k++;
        }
    }
};


法三:网上提供的一种解法,更巧妙,,就是让i,j,k表示 分别表示[0,i]为0,[i+1, j]为1,[j+1,k]为2,然后用指针p遍历,并作代码中相应的处理。

class Solution {
public:
    void sortColors(int A[], int n) {
        int i = -1, j = -1, k = -1;   // 分别表示[0,i]为0,[i+1, j]为1,[j+1,k]为2
        for(int p = 0; p < n; p++){
            if(A[p] == 0){   // 要理解
                A[++k] = 2;
                A[++j] = 1;
                A[++i] = 0;
            }else if(A[p] == 1){
                A[++k] = 2;
                A[++j] = 1;
            }else A[++k] = 2;
        }
    }
};





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值