/* 题目:给定两个排好序的数组,数组大小为m和n,找出中间数值。如果(m+n)为偶数,则表示中间数值不存在, 则中间数值表示中间两个数值的(Aj + Bj)/2。 问题一般化:找出两个数组中第K大的数值。 方法: 1.将两个数组merge,然后找下标为 k-1 的数即可。复杂度为O(m+n)。 2.使用两个指针,如快排的二分法一样,将指针在两个数组上游走,只取前K个值,并不判断后面的数值。复杂度为O(k) 3.最优的方法。达到O(log(M)+log(N)),要达到这样的复杂度,必须每次将解空间缩小一半。经典如二分法。 */ int findKthSmallest(int A[], int m, int B[], int n, int k){ //利用这种方法确定i,j只是众多方法中的一个,也可以使用其他方法,只要满足 i+j = k - 1即可 int i = (int)((double)m / (m + n) * (k-1)); int j = k - 1 - i; //这个边界条件非常重要,防止出现 i-1和i=m时没有值,而且使用三目运算符是非常明智的想法 int Ai_1 = (i == 0) ? INT_MIN : A[i - 1]; int Bj_1 = (j == 0) ? INT_MIN : B[j - 1]; int Ai = (i == m) ? INT_MAX : A[i]; int Bj = (j == n) ? INT_MAX : B[j]; //这是跳出循环的条件,只要满足这个条件递归才会结束 if (A[i] > Bj_1 && A[i] < Bj){ return A[i]; } else if (B[j] > Ai_1 && B[j] < A[i]){ return B[j]; } if (Ai > Bj) { // 最后的 k - j - 1非常重要,因为已经去掉了j+1个不可能的值了,所以是求第k - j - 1大的数了 return findKthSmallest(A, i, B + j + 1, n - j - 1, k - j - 1); } else{ return findKthSmallest(A + i + 1, m - i - 1, B ,j, k - i - 1); } }
int findKthSmallest(TreeNode* root, int& k) { if (root == NULL) return 0; int ans = findKthSmallest(root->left, k); if (k == 0) return ans; if (--k == 0) return root->val; return findKthSmallest(root->right, k); }
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int m = nums1.size(); int n = nums2.size(); if ((m+n) & 1) { return (double)findKthSmallest(&nums1[0], nums1.size(), &nums2[0], nums2.size(), (m+n+1)/2); } else { return (double)(findKthSmallest(&nums1[0], nums1.size(), &nums2[0], nums2.size(), (m+n)/2) + findKthSmallest(&nums1[0], nums1.size(), &nums2[0], nums2.size(), (m+n)/2+1))/2.0; } }
int minMoves2(vector<int>& nums) { // This could be the larger one of the two center elements if the array length is even. int median = findKthSmallest(nums, 0, nums.size(), nums.size() / 2); int move = 0; for (int i = 0; i < nums.size(); i++) { move += abs(nums[i] - median); } return move; }
int findKthSmallest(int* a, int m, int *b, int n, int k) { if (m > n) { return findKthSmallest(b, n, a, m, k); } if (m == 0) { return b[k-1]; } if (k == 1) { return min(a[0], b[0]); } int i = min(m, k/2); int j = k - i; if (a[i-1] == b[j-1]) { return a[i-1]; } else if (a[i-1] < b[j-1]) { return findKthSmallest(a+i, m-i, b, n, k-i); } else { return findKthSmallest(a, m, b+i, n-i, k-i); } }
int kthSmallest(TreeNode* root, int k) { return findKthSmallest(root, k); }