Quickselect works identical to quicksort in that we:
Pick a pivot
Partition the data into two where:
Numbers less than the pivot go to the left
Numbers greater than the pivot go to the right
However, instead of recursing into both sides as in Quicksort, quickselect only recurs into one side; whichever one would have our kth largest element. The main thing to note here is that our pivot at any given partition will always end up at the correct index. Therefore, we just need to check:
If our pivot is at our “kth largest” index, return the number at that index.
If our pivot comes before the “kth largest” index, perform quickselect on the right partition.
If our pivot comes after the “kth largest” index, perform quickselect on the left partition.
Random rand=newRandom(); publicintfindKthLargest(int[] nums, int k) { int n=nums.length; int low=0; int high=n-1; while(low<=high){ int j=partition(nums,low,high); if(j<n-k){ low=j+1; }elseif(j>n-k){ high=j-1; }else{ return nums[j]; } } return -1; }
intpartition(int[] nums, int start, int end){ int index=rand.nextInt(end-start+1)+start; swap(nums,start,index); int pivot=nums[start]; int i=start+1; int j=end; //[start,i) <=pivot //[i,j] unknown //(j,end] >pivot while(i<=j){ if(nums[j]>pivot){ j--; }else{ swap(nums,i++,j); } } swap(nums,start,j); return j; }
voidswap(int[] nums, int i, int j){ if(i==j){ return; } int temp=nums[i]; nums[i]=nums[j]; nums[j]=temp; }
462. Minimum Moves to Equal Array Elements II
In one move, you can increment or decrement an element of the array by 1.
Random rand=newRandom(); publicintminMoves2(int[] nums) { int median=kthSmallest(nums,nums.length/2); int res=0; for (int num : nums) { res+=Math.abs(num-median); } return res; }
intkthSmallest(int[] nums, int k){ int n=nums.length; int left=0; int right=n-1; while(left<=right){ int index=partition(nums,left,right); if(index==k){ return nums[index]; }elseif(index<k){ left=index+1; }else{ right=index-1; } } return -1; }
intpartition(int[] nums, int start, int end){ int index=start+rand.nextInt(end-start+1); swap(nums,start,index); int left=start+1; int right=end; int pivot=nums[start]; //[start+1,left) <=pivot //[left,right] unknown //(right,end] >pivot while(left<=right){ if(nums[right]>pivot){ right--; }else{ swap(nums,left++,right); } } swap(nums,start,right); return right; }
voidswap(int[] nums, int i, int j){ if(i==j){ return; } int temp=nums[i]; nums[i]=nums[j]; nums[j]=temp; /* a=a^b; b=a^b;//a^b^b a=a^b; //a^b^a*/ }
453. Minimum Moves to Equal Array Elements
let’s define sum as the sum of all the numbers, before any moves; minNum as the min number int the list; n is the length of the list;
After, say m moves, we get all the numbers as x , and we will get the following equation
1
sum + m * (n - 1) = x * n
and actually,
1
x = minNum + m
This part may be a little confusing, but @shijungg explained very well. let me explain a little again. it comes from two observations:
the minum number will always be minum until it reachs the final number, because every move, other numbers (besides the max) will be increamented too;
from above, we can get, the minum number will be incremented in every move. So, if the final number is x, it would be minNum + moves;
and finally, we will get
1
sum - minNum * n = m
This is just a math calculation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
//sum+m*(n-1)=n*x //x=minNum+m //sum+m*(n-1)=n*(minNum+m) //sum-m=n*minNum publicintminMoves(int[] nums) { int n=nums.length; int sum=0; int min=Integer.MAX_VALUE; for (int num : nums) { sum+=num; min=Math.min(min,num); } return sum-n*min; }
classSolution { public: longlongminSumSquareDiff(vector<int>& nums1, vector<int>& nums2, int k1, int k2){ int n = nums1.size(); vector<int> diff(n); for(int i = 0; i<n; ++i) { diff[i] = abs(nums1[i] - nums2[i]); } //max_element() return an iterator pointing to the max element //to get the actual value of max element, must use * int M = *max_element(diff.begin(), diff.end()); vector<int> bucket(M+1); for(int i = 0 ; i<n; ++i) { bucket[diff[i]]++; } int k = k1 + k2; for(int i = M; i > 0; --i) { if(bucket[i] > 0) { int minus = min(bucket[i], k); bucket[i] -= minus; //every diff in bucket[i] is decreased by one //in turn, they add to diff num in bucket[i-1] bucket[i-1] += minus; k -= minus; } } longlong ans = 0; for(longlong i = M; i > 0; --i) { ans += bucket[i]*i*i; } return ans; } };