Leetcode41. First Missing Positive

Hard but Interesting!

开始没想明白,后来看了discuss发现,自己肯定想不出来…都是套路。

套路1:

数组长度为n,则最多有n个正整数。那么我每次遇到一个在[1,n]里的正整数,就把它放到对应的位置,如正整数i放到nums[i-1](值为i的元素与i应在的nums[i-1]交换即可)(1放到nums[0])。不能换的就等着能换的来换(所以要用while循环不能用for循环)。

之后再次遍历,遇到的第一个不对应的即是第一个缺少的。

public class Solution {
    public int firstMissingPositive(int[] A) {
        int i = 0;
        // note we can't use for loop here
        // for(int i=0;i<n;i++){
        //     if(nums[i]==i+1||nums[i]<=0||nums[i]>n) continue;
        //     while(i!=nums[i]-1)
        //         swap(nums,i,nums[i]-1); //nums[nums[i]-1] is right now(=nums[i]) but nums[i] not definitely equals i+1,so we need a while loop
        // }
        while(i < A.length){
            if(A[i] == i+1 || A[i] <= 0 || A[i] > A.length) i++;
            else if(A[A[i]-1] != A[i]) swap(A, i, A[i]-1); //nums[nums[i]-1] is right now(=nums[i]) but nums[i] not definitely equals i+1,so still need to loop
            else i++;
        }
        i = 0;
        while(i < A.length && A[i] == i+1) i++;
        return i+1;
    }
    
    private void swap(int[] A, int i, int j){
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
    private void swap2(int[] nums,int i,int j){
        if(i!=j){
            nums[i]=nums[i]^nums[j];
            nums[j]=nums[i]^nums[j];
            nums[i]=nums[i]^nums[j];
        }
    }
}

swap 6,7ms 60% 可以了。

swap2 9,10ms。看来这么写效率其实并不高。

套路2:

另外一种思路则是递进的。如果能直接想到上面的思路1,就用思路1就挺好,只不过有时候可能会绕进去,那么可以用思路2。

https://leetcode.com/problems/first-missing-positive/discuss/17073/Share-my-O(n)-time-O(1)-space-solution

可以去看看。主要是partition的思路可以学习一下,以及用符号来表示更多信息的套路。9ms,并不快。

public class Solution {
 public int firstMissingPositive(int[] A) {
    int n=A.length;
    if(n==0)
        return 1;
    int k=partition(A)+1;
    int temp=0;
    int first_missing_Index=k;
    for(int i=0;i<k;i++){
        temp=Math.abs(A[i]);
        if(temp<=k)
            A[temp-1]=(A[temp-1]<0)?A[temp-1]:-A[temp-1];
    }
    for(int i=0;i<k;i++){
        if(A[i]>0){
            first_missing_Index=i;
            break;
        }
    }
    return first_missing_Index+1;
}

public int partition(int[] A){
    int n=A.length;
    int q=-1;
    for(int i=0;i<n;i++){
        if(A[i]>0){
            q++;
            swap(A,q,i);
        }
    }
    return q;
}
    private void swap(int[] A, int i, int j){
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }


}

自己又改良了一下partition,6-10ms。但实在没什么用,最好还是用第一种方法。

public class Solution {
 public int firstMissingPositive(int[] A) {
    int n=A.length;
    if(n==0)
        return 1;
    int k=splitPosNeg(A)+1;
    int temp=0;
    int first_missing_Index=k;
    for(int i=0;i<k;i++){
        temp=Math.abs(A[i]);
        if(temp<=k)
            A[temp-1]=(A[temp-1]<0)?A[temp-1]:-A[temp-1];
    }
    for(int i=0;i<k;i++){
        if(A[i]>0){
            first_missing_Index=i;
            break;
        }
    }
    return first_missing_Index+1;
}
private int splitPosNeg(int[] A){
    int l=0,r=A.length-1;
    while(l<r){
        while(r>=0&&A[r]<=0) r--;
        while(l<=A.length-1&&A[l]>0) l++;
        if(l<r) swap(A,l,r);
    }
    if(A[r]>0)
        return r;
    else
        return -1;
}
public int partition(int[] A){
    int n=A.length;
    int q=-1;
    for(int i=0;i<n;i++){
        if(A[i]>0){
            q++;
            swap(A,q,i);
        }
    }
    return q;
}
    private void swap(int[] A, int i, int j){
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }


}

 

posted @ 2018-12-28 17:06  大胖子球花  阅读(87)  评论(0)    收藏  举报