leetcode -- Binary search (6)

来源:互联网 发布:java小写字母转大写 编辑:程序博客网 时间:2024/05/29 14:43

Kth Smallest Element in a Sorted Matrix

Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.

Note that it is the kth smallest element in the sorted order, not the kth distinct element.

Example:

matrix = [   [ 1,  5,  9],   [10, 11, 13],   [12, 13, 15]],k = 8,return 13.

解法1:

1. 第K大或第K小的思路都是根据左边元素的个数判断。sorted matrix可以看作是部分有序。因此我们可以在每个有序子序列判断目标值左边元素的个数。

2. 这道也算是使用binary search进行guess and improve。既然不知道是哪一个,又很难实现快速选择算法,那就可以猜且进行逼近。

3. 如果smallerNum == k,则有 mid >= solution;因为可能存在重复, smallerNum > k时,mid也有可能是solution

    int kthSmallest(vector<vector<int>>& matrix, int k) {        int n = matrix.size();        int left = matrix[0][0];        int right = matrix[n-1][n-1];        while (left < right){     //循环的条件是left<=solution<=right,当left>=right时,left=solution=right            int mid = left + (right - left) / 2;            int smallerNum = 0;            for (int i = 0; i < n; i++){                int pos = upper_bound(matrix[i].begin(), matrix[i].end(), mid) - matrix[i].begin();  //查找每一行小于等于mid的元素个数                smallerNum += pos;            }            if (smallerNum < k) left = mid + 1;            else right = mid;   //不能是mid-1,因为mid可能是最后的答案        }        return left;    }


解法2:在解法1中并没有利用好“列是排序的”这一条件。依据 Search a 2D Matrix II的思路,我们可以以O(n)复杂度在每行进行查找。

    int kthSmallest(vector<vector<int>>& matrix, int k) {        int n = matrix.size();        int left = matrix[0][0];        int right = matrix[n-1][n-1];        while (left < right){   //循环的条件是left<=solution<=right,当left>=right时,left=solution=right            int mid = left + (right - left) / 2;            int smallerNum = 0;            int j = n - 1;            for (int i = 0; i < n && j > -1; i++){                while (j > -1 && mid < matrix[i][j]) j--;   //O(n)的查找,因为列是排序的,因此mid < matrix[i][j]时我们可以排除一列。                smallerNum += j + 1;            }            if (smallerNum < k) left = mid + 1;            else right = mid;           }        return left;    }


Intersection of Two Arrays II

Given two arrays, write a function to compute their intersection.

Example:
Given nums1 = [1, 2, 2, 1]nums2 = [2, 2], return [2, 2].

Note:

  • Each element in the result should appear as many times as it shows in both arrays.
  • The result can be in any order.

Follow up:

  • What if the given array is already sorted? How would you optimize your algorithm?
  • What if nums1's size is small compared to nums2's size? Which algorithm is better?
  • What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once?

原题:使用hashmap

    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {        unordered_map<int, int> rcd;        vector<int> rst;        for (int n : nums1){            if (rcd.find(n) == rcd.end()) rcd[n] = 1;            else rcd[n]++;        }        for (int n : nums2){            if (rcd.find(n) != rcd.end() && rcd[n] != 0){                rcd[n]--;                rst.push_back(n);            }        }        return rst;    }


Follow up 1: 

1. 如果两个数组都是sorted,可以使用双指针,复杂度O(m + n)

2. 如果只有一个sorted, 则在sorted array中进行二分查找,复杂度O(mlogn)或O(nlogm)

    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {        int i = 0, j = 0;        vector<int> rst;        while (i < nums1.size() && j < nums2.size()){            if (nums1[i] == nums2[j]) {                rst.push_back(nums1[i]);                i++;                j++;            }            else if (nums1[i] > nums2[j]) j++;            else i++;        }        return rst;    }

Follow up 3: 将nums1使用hashmap;如果sorted的话使用双指针;每次从磁盘中读取一部分nums2



0 0
原创粉丝点击