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; } }

浙公网安备 33010602011771号