【leetcode】41.(Hard)First Missing Positive
阿新 • • 發佈:2018-12-18
解題思路: 歸併排序——剔重——找到最小非負數——折半查詢 這道題就是需要考慮的邊界比較多 另外就是對重複數字的處理
提交程式碼:
class Solution {
public int firstMissingPositive(int[] nums) {
if(nums.length==0) return 1;
if(nums.length==1)
return (nums[0]<=0||nums[0]>=2)?1:2;
//排序
mergeSort(nums,0,nums.length-1);
//剔重
int i=1,j=1,flagnum=nums[0];
while(i<nums.length) {
while(i<nums.length&&nums[i]==flagnum)
i++;
if(i<nums.length) {
nums[j++]=nums[i];
flagnum=nums[i++];
}
}
int len=j;
//邊界
if (nums[len-1]<=0||nums[0]>=2) return 1;
if((nums[len-1]-nums[0])==(len-1))
return nums[len-1]+1;
//找到第一個0及以上的數
int mid,left=0,right=len;
int posmin=0;
while(left<=right) {
if(nums[left]>0) {
posmin=left;
break ;
}
posmin=(left+right)/2;
if(nums[posmin]>0) right=posmin;
else if(nums[posmin]==0) break;
else left=posmin+1;
}
if(nums[posmin]>=2) return 1;
//此時nums[left]是0 或者1
left=posmin;right=len-1;
while(left<right) {
if(left==(right-1)) return nums[left]+1; //134567
mid=(left+right)/2;
if((mid-left)!=(nums[mid]-nums[left])) right=mid;
else if((right-mid)!=(nums[right]-nums[mid])) left=mid;
else {
if((nums[mid+1]-nums[mid])!=1) return nums[mid]+1;
else return nums[right]+1;
}
}
if(nums[left]==1) return 2;
else return nums[right]-1;
}
public void mergeSort(int[] nums,int left,int right){
if(left>=right) return;
int mid=(left+right)/2;
mergeSort(nums,left,mid);
mergeSort(nums,mid+1,right);
merge(nums,left,mid,right);
}
public void merge(int[] nums,int left,int mid,int right) {
if(left==right) return;
int len=right-left+1;
int tmp[]=new int[len];
int i=left,j=mid+1,k=0;
while(i<=mid&&j<=right)
tmp[k++]=nums[i]<nums[j]?nums[i++]:nums[j++];
while(i<=mid)
tmp[k++]=nums[i++];
while(j<=right)
tmp[k++]=nums[j++];
for(k=0;k<len;k++)
nums[left++]=tmp[k];
}
}
執行結果: