240-搜索二维矩阵 II

题目

编写一个高效的算法来搜索 *m* x *n* 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

  • 每行的元素从左到右升序排列。
  • 每列的元素从上到下升序排列。

示例 1:

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true

示例 2:

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
输出:false

思路

  1. 线性搜索:

    从右上往左下搜索。如果比右上大,就去下一行。如果比下一行小,就去该行左侧。

  2. 二分搜索

    指定左右、上下边界,与边界中心进行比较。

    • 如果比边界中心小:去中心左侧和上侧搜索。
    • 如果比边界中心大:去中心右侧和下侧搜索。

代码

  1. 线性搜索

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Solution {
    public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
    int y = 0,x = matrix[0].size()-1;
    for(;y<matrix.size()&&x>=0;){
    if(matrix[y][x]==target) return true;
    if(matrix[y][x]<target) y++;
    else x--;
    }
    return false;
    }
    }
  2. 二分搜索

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class Solution {
    public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
    int m = matrix.size(), n = matrix[0].size();
    return searchMatrix(matrix,target,0,m-1,0,n-1);
    }
    bool searchMatrix(vector<vector<int>>& matrix,int target,int ru,int rd,int cl,int cr){
    if(ru>rd||cl>cr) return false;
    int rm = (ru+rd)/2, cm = (cl+cr)/2;
    if(matrix[rm][cm]==target) return true;
    else if(matrix[rm][cm]>target){
    return searchMatrix(matrix,target,ru,rm-1,cl,cr)||
    searchMatrix(matrix,target,ru,rd,cl,cm-1);
    }else{
    return searchMatrix(matrix,target,ru,rd,cm+1,cr)||
    searchMatrix(matrix,target,rm+1,rd,cl,cr);
    }
    }
    };

528-按权重随机选择

528. 按权重随机选择

给定一个正整数数组 w ,其中 w[i]

表下标 i 的权重(下标从 0 开始),请写一个函数 pickIndex ,它可以随机地获取下标 i,选取下标 i 的概率与 w[i] 成正比。

例如,对于 w = [1, 3],挑选下标 0 的概率为 1 / (1 + 3) = 0.25 (即,25%),而选取下标 1 的概率为 3 / (1 + 3) = 0.75(即,75%)。

也就是说,选取下标 i 的概率为 w[i] / sum(w)

示例 1:

输入:
[“Solution”,”pickIndex”]
[[[1]],[]]
输出:
[null,0]
解释:
Solution solution = new Solution([1]);
solution.pickIndex(); // 返回 0,因为数组中只有一个元素,所以唯一的选择是返回下标 0。

示例 2

输入:
[“Solution”,”pickIndex”,”pickIndex”,”pickIndex”,”pickIndex”,”pickIndex”]
[[[1,3]],[],[],[],[],[]]
输出:
[null,1,1,1,1,0]
解释:
Solution solution = new Solution([1, 3]);
solution.pickIndex(); // 返回 1,返回下标 1,返回该下标概率为 3/4 。
solution.pickIndex(); // 返回 1
solution.pickIndex(); // 返回 1
solution.pickIndex(); // 返回 1
solution.pickIndex(); // 返回 0,返回下标 0,返回该下标概率为 1/4 。**

由于这是一个随机问题,允许多个答案,因此下列输出都可以被认为是正确的:
[null,1,1,1,1,0]
[null,1,1,1,1,1]
[null,1,1,1,0,0]
[null,1,1,1,0,1]
[null,1,0,1,0,0]
……
诸若此类。

提示:

  • 1 <= w.length <= 10000
  • 1 <= w[i] <= 10^5
  • pickIndex 将被调用不超过 10000

思路

随机+二分查找

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
vector<int> presum;
Solution(vector<int>& w) {
presum.resize(w.size()+1,0);
for(int i=1;i<=w.size();i++) presum[i] = presum[i-1]+w[i-1];
}

int pickIndex() {
int rnum = rand()%presum.back()+1;
int left = 1, right = presum.size()-1,mid;
while(left<right){
mid=(left+right)/2;
if(presum[mid]>=rnum) right=mid;
else left=mid+1;
}
return right-1;
}
};