publicclassLeetCode162 { publicintfindPeakElement(int[] nums) { //nums[i-1]<nums[i]>nums[i+1] //nums[i-1]>nums[i]<nums[i+1], i=i+1 波谷时向左向右都可 //nums[i-1]>nums[i]>nums[i+1], i=i-1 //nums[i-1]<nums[i]<nums[i+1], i=i+1 int n=nums.length; int left=0; int right=n-1; int res=0; while(left<=right){ int mid=left+(right-left)/2; int c=compare(nums,mid-1,mid,mid+1); if(c==0){ res=mid; break; }elseif(c>0){ left=mid+1; }else{ right=mid-1; } } return res; }
intcompare(int[] nums, int pre, int cur, int post){ int preVal= pre==-1 ? Integer.MIN_VALUE : nums[pre]; int postVal= post==nums.length ? Integer.MIN_VALUE : nums[post]; int curVal=nums[cur]; if(curVal>preVal && curVal>postVal){ return0; } if(curVal<preVal && curVal>postVal){ return -1; } return1; } }
167. Two Sum II - Input Array Is Sorted
注意:
already sorted in non-decreasing order
there is exactly one solution
must use only constant extra space
time and space complexity:
Two pointers: O(n) time and O(1) space
Dictionary: O(n) time and O(n) space
Binary search: O(nlogn) time and O(1) space
法一: two pointers
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
publicint[] twoSum(int[] numbers, int target) { int n=numbers.length; int left=0; int right=n-1; while(left<right){ int sum=numbers[left]+numbers[right]; if(sum==target){ returnnewint[]{left+1,right+1}; }elseif(sum>target){ right--; }else{ left++; } } returnnull; }
publicint[] twoSum(int[] numbers, int target) { int n=numbers.length; for (inti=0; i < n; i++) { int temp=target-numbers[i]; int left=i+1; int right=n-1; int mid=0; while(left<=right){ mid=left+(right-left)/2; if(numbers[mid]==temp){ returnnewint[]{i+1,mid+1}; }elseif(numbers[mid]<temp){ left=mid+1; }else{ right=mid-1; } } } returnnull; }
209. Minimum Size Subarray Sum
法一: sliding window
O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
publicintminSubArrayLen(int target, int[] nums) { int n=nums.length; int min=Integer.MAX_VALUE; int l=0; int r=0; int sum=0; while(r<n){ //[l,r) sum+=nums[r++]; while(sum>=target){ min=Math.min(min,r-l); sum-=nums[l++]; } } return min==Integer.MAX_VALUE ? 0 : min; }
publicintminSubArrayLen(int target, int[] nums) { int n=nums.length; int l=0; int r=n-1; int res=0; while(l<=r){ int mid=l+(r-l)/2; if(possible(nums,target,mid+1)){ res=mid+1; r=mid-1; }else{ l=mid+1; } } return res; }
booleanpossible(int[] nums, int target, int size){ int sum=0; int i=0; for (; i < size; i++) { sum+=nums[i]; if(sum>=target){ returntrue; } } //[0,end] int j=0; //[j,i] while(i<nums.length){ sum+=nums[i++]; sum-=nums[j++]; if(sum>=target){ returntrue; } } returnfalse; }
publicbooleansearchMatrix(int[][] matrix, int target) { int row=matrix.length; int col=matrix[0].length; for (inti=0; i < row; i++) { if(find(matrix[i],target,col)){ returntrue; } } returnfalse; }
booleanfind(int[] arr, int target, int n){ int left=0; int right=n-1; while(left<=right){ int mid=left+(right-left)/2; if(arr[mid]==target){ returntrue; }elseif(arr[mid]<target){ left=mid+1; }else{ right=mid-1; } } returnfalse; }
278. First Bad Version
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
publicintfirstBadVersion(int n) { int l=0; int r=n; int res=n; while(l<=r){ int mid=l+(r-l)/2; if(isBadVersion(mid)){ res=mid; r=mid-1; }else{ l=mid+1; } } return res; }
287. Find the Duplicate Number
You must solve the problem without modifying the array nums and uses only constant extra space.
Approach 3: Negative Marking
Given an array of integers nums containing n + 1 integers where each integer is in the range [1, n] inclusive.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
publicintfindDuplicate(int[] nums) { int n=nums.length; int res=-1; for (int num : nums) { int cur=Math.abs(num); if(nums[cur]<0){ res=cur; break; } nums[cur]*=-1; } for (inti=0; i < n; i++) { if(nums[i]<0){ nums[i]*=-1; } } return res; }
Approach 7: Floyd’s Tortoise and Hare (Cycle Detection)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
publicintfindDuplicate(int[] nums) { int head=nums[0]; int fast=head; int slow=head; do{ fast=nums[nums[fast]]; slow=nums[slow]; }while(fast!=slow); int p=head; while(slow!=p){ slow=nums[slow]; p=nums[p]; } return p; }
publicintfirstMissingPositive(int[] nums) { int n=nums.length; int i=0; while(i<n){ //[1,2,3,...,n] int correct=nums[i]-1; if(nums[i]>0 && nums[i]<=n && nums[i]!=nums[correct]){ int temp=nums[i]; nums[i]=nums[correct]; nums[correct]=temp; }else{ i++; } } for (intj=1; j <= n; j++) { if(nums[j-1]!=j){ return j; } } return n+1; }
392. Is Subsequence
Follow up: Suppose there are lots of incoming s, say s1, s2, ..., sk where k >= 109, and you want to check one by one to see if t has its subsequence. In this scenario, how would you change your code?
publicbooleansearch(int[] nums, int target) { int n=nums.length; int left=0; int right=n-1; while(left<=right){ int mid=(left+right)>>1; if(nums[mid]==target){ returntrue; } if(nums[left]<nums[mid] || nums[left]==nums[mid] && nums[left]!=nums[right]){ //[left,mid] sorted if(nums[left]<=target && nums[mid]>target){ //target in sorted range right=mid-1; }else{ left=mid+1; } }elseif(nums[left]>nums[mid]){ //[mid,right] sorted if(nums[mid]<target && nums[right]>=target){ //target in sorted range left=mid+1; }else{ right=mid-1; } }else{ //left == mid ==right, don't know which part is sorted //but can safely narrow current interval to [left+1,right-1] left++; right--; } } returnfalse; }
二分答案法模板
找满足条件的最小整数值
1 2 3 4 5 6 7 8 9 10 11
while(left<right){ //[left,right) int mid=(left+right)/2; // while(!condition){ left=mid+1; }else{ right=mid; } } return left; //or right, since left=right
publicintminCapability(int[] nums, int k) { int left= Arrays.stream(nums).min().getAsInt(); int right= Arrays.stream(nums).max().getAsInt(); int n=nums.length; while(left<right){ //[left,right) int mid=left+(right-left)/2; int take=0; for (inti=0; i < n; i++) { if(nums[i]<=mid){ take++; i++; } } if(take<k){ left=mid+1; }else{ right=mid; } } return left; }
publicintshipWithinDays(int[] weights, int days) { int n=weights.length; int left= Arrays.stream(weights).max().getAsInt(); int right=(int)1e8; while(left<right){ //[left,right) int mid=left+(right-left)/2; int take=0; int cur=0; for (inti=0; i < n; i++) { cur+=weights[i]; if(i<n-1 && cur+weights[i+1]>mid){ cur=0; take++; } } take++; if(take>days){ left=mid+1; }else{ right=mid; } } return left; }
publicintmaximizeSweetness(int[] sweetness, int k) { //maximize my piece //minimize others' pieces int n=sweetness.length; if(n==0){ return0; } int left=1; int right=(int)1e9; while(left<right){ //(left,right] int mid=(right+left+1)/2;
int cur=0; int count=0; for (inti=0; i < n; i++) { cur+=sweetness[i]; if(cur>=mid){ count++; cur=0; } } if( count>k){ left=mid; }else{ right=mid-1; } } return right; //or return left }
publicintminDays(int[] bloomDay, int m, int k) { int n=bloomDay.length; if(n<m || n<m*k){ return -1; } int left=1; int right=(int)1e9; while(left<right){ //[left,right) int mid=(left+right)/2; int count=0; int cur=0; for (inti=0; i < n; i++) { if(bloomDay[i]<=mid){ cur++; if(cur==k){ count++; cur=0; } }else{ cur=0; } } if(count<m){ left=mid+1; }else{ right=mid; } } return left; }
1539. Kth Missing Positive Number
easy题的edge case也不easy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
publicintfindKthPositive(int[] arr, int k) { int n=arr.length; if(k<=arr[0]-1){ return k; } k-=arr[0]-1; int cur=0; for (inti=0; i < n-1; i++) { cur=arr[i+1]-arr[i]-1; if(k>cur){ k-=cur; }else{ return arr[i]+k; } } return arr[n-1]+k; }
Could you solve this problem in less than O(n) complexity?
publicintfindKthPositive(int[] arr, int k) { intleft=0, right = arr.length - 1; while (left <= right) { intpivot= left + (right - left) / 2; // If number of positive integers // which are missing before arr[pivot] // is less than k --> // continue to search on the right. if (arr[pivot] - pivot - 1 < k) { left = pivot + 1; // Otherwise, go left. } else { right = pivot - 1; } }
// At the end of the loop, left = right + 1, // and the kth missing is in-between arr[right] and arr[left]. // The number of integers missing before arr[right] is // arr[right] - right - 1 --> // the number to return is // arr[right] + k - (arr[right] - right - 1) = k + left return left + k; }
1802. Maximum Value at a Given Index in a Bounded Array
publicintmaxValue(int n, int index, int maxSum) { maxSum -= n; intleft=0, right = maxSum, mid; while (left < right) { mid = (left + right + 1) / 2; if (test(n, index, mid) <= maxSum) left = mid; else right = mid - 1; } return left + 1; }
privatelongtest(int n, int index, int a) { //左边到0或到头 intb= Math.max(a - index, 0); longres= (long)(a + b) * (a - b + 1) / 2; //右边到0或到头 b = Math.max(a - ((n - 1) - index), 0); res += (long)(a + b) * (a - b + 1) / 2; return res - a; //中间加了两次,需减掉 }
publicintmaxValue(int n, int index, int maxSum) { int left=1; int right=(int)1e9; while(left<right){ //(left,right] int mid=(left+right+1)/2; int sum=0; int pre=mid; a:{ for (inti= index; i >= 0; i--) { sum+=pre==1 ? 1 : --pre; if(sum>maxSum){ break a; } } pre=mid; for (inti= index+1; i < n; i++) { sum+=pre==1 ? 1 : --pre; if(sum>maxSum){ break a; } } }
publicintsmallestDistancePair(int[] nums, int k) { int n=nums.length; Arrays.sort(nums); //kth smallest dif => //smallest dif satisfying count>=k //count: number of pairs with distance <= mi int low=0; int high=nums[n-1]-nums[0]; while(low<high){ int mid=(low+high)/2; int count=0; int left=0; for (intright=0; right < n; right++) { while(nums[right]-nums[left]>mid){ left++; } //([left,right-1] right) count+=right-left; } if(count<k){ low=mid+1; }else{ high=mid; } } return low; }
publicintmaxDistance(int[] position, int m) { //maximize minimum gap Arrays.sort(position); int n=position.length; int left=1; int right=position[n-1]; while(left<right){ //(left,right] int mid=(left+right+1)/2; int count=1; int pre=position[0]; for (inti=1; i < n; i++) { if(position[i]-pre>=mid){ pre=position[i]; count++; if(count>=m){ break; } } } if(count<m){//invalid right=mid-1; }else{//valid, try larger gap left=mid; } } return left; }
publicclassLeetCode1428 { interfaceBinaryMatrix { publicintget(int row, int col); public List<Integer> dimensions(); } int row; int col; int res; publicintleftMostColumnWithOne(BinaryMatrix binaryMatrix) { List<Integer> list=binaryMatrix.dimensions(); row=list.get(0); col=list.get(1); res=col; for (inti=0; i < row; i++) { search(binaryMatrix,i); } return res==col ? -1 : res; }
voidsearch(BinaryMatrix binaryMatrix, int i){ int left=0; int right=col-1; while(left<right){ //[left,right) int mid=(left+right)/2; int val=binaryMatrix.get(i,mid); if(val==0){ left=mid+1; }else{ right=mid; } } if(binaryMatrix.get(i,left)==1){ res=Math.min(res,left); } } }
class Solution { Random rand; int total; int n; int[] prefix; public Solution(int[] w) { rand=new Random(); n=w.length; prefix=new int[n]; prefix[0]=w[0]; for (int i = 1; i < n; i++) { prefix[i]=prefix[i-1]+w[i]; } total= Arrays.stream(w).sum(); }
public int pickIndex() { int target=rand.nextInt(total)+1; //[1,total] return binarySearch(target); }
int binarySearch(int target){ //[1,a] [a+1,b] [b+1,c] //smallest a where a >=target int left=0; int right=n; while(left<right){ //[left,right) int mid=(left+right)/2; if(prefix[mid]<target){ left=mid+1; }else{ right=mid; } } return left; } }
publicintsingleNonDuplicate(int[] nums) { //a a b c c //a b b c c //a a b b c //find the smallest even index where nums[i]!=nums[i+1] int n=nums.length-1; int left=0; int right=n; while(left<right){ //[left,right) int mid=(left+right)/2; if((mid&1)==1){ mid--; } if(nums[mid]==nums[mid+1]){ left=mid+2; }else{ right=mid; } } return nums[left]; }
410. Split Array Largest Sum
classic min-max: Return the minimized largest sum of the split.
publicintsplitArray(int[] nums, int k) { int n=nums.length; int l=0; int r=(int)1e9; //the smallest sum that satisfies while(l<r){ //[l,r) int mid=(l+r)>>1; int count=0; int sum=0; int i=0; for (; i < n; i++) { if(nums[i]>mid){ break; } sum+=nums[i]; if(sum>mid){ count++; sum=nums[i]; } } count++; if(i<n || count>k){//not valid l=mid+1; }else{ r=mid; } } return l; }
publicintmaxLength(int[] ribbons, int k) { Arrays.sort(ribbons); int n=ribbons.length; int l=0; int r=100000; while(l<r){ //(l,r] int mid=(l+r+1)/2; int count=0; for (inti= n-1; i >=0; i--) { int num=ribbons[i]; count+=num/mid; if(count>=k || num<mid){ break; } } if(count<k){ r=mid-1; }else{ l=mid; } } return l; }
1498. Number of Subsequences That Satisfy the Given Sum Condition
publicintnumSubseq(int[] nums, int target) { Arrays.sort(nums); int res=0; int mod=(int)1e9+7; int n=nums.length; int[] pow=newint[n+1]; pow[0]=1; for (inti=1; i <= n; i++) { pow[i]=(pow[i-1]<<1)%mod; } for (intleft=0; left < n; left++) { //nums[left]+nums[right]<=target int right=findFirstSmall(nums,target-nums[left])-1; //[left,right] if(right-left>=0){ res+=pow[right-left]; res%=mod; } } return res; }
privateintfindFirstSmall(int[] nums, int target){ //find smallest idx where nums[idx]>target int left=0; int right=nums.length; while(left<right){ //[left,right) int mid=(left+right)/2; if(nums[mid]<=target){ left=mid+1; }else{ right=mid; } } return left; }
publiclongminCost(int[] nums, int[] cost) { int left= Arrays.stream(nums).min().getAsInt(); int right=Arrays.stream(nums).max().getAsInt(); long res=0; while(left<right){ int mid=(left+right)/2; long cost1=helper(nums,cost,mid); long cost2=helper(nums,cost,mid+1); if(cost1>cost2){ res=cost2; left=mid+1; }else{ res=cost1; right=mid; } } return res; }
privatelonghelper(int[] nums, int[] cost, int target){ long res=0; for (inti=0; i < nums.length; i++) { res+=1L*Math.abs(target-nums[i])*cost[i]; } return res; }