leetcode中的二分查找

 

二分查找

题目链接

给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索$nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1

提示:

你可以假设 nums 中的所有元素是不重复的。
n 将在 [1, 10000]之间。
nums 的每个元素都将在 [-9999, 9999]之间。

class Solution {
public:

    int search(vector<int>& nums, int target) {
        int n=nums.size();
        int l=0,r=n-1;
        int ans=0;
        while(r>=l){
            int mid=(l+r)/2;
            if(nums[mid]<=target){
                ans=mid;
                l=mid+1;
            }
            else{
                r=mid-1;
            }
        }
        if(ans==-1||nums[ans]!=target){
            return -1;
        }
        return ans;    
    }
};

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为O(logn)的算法。

示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4

提示:

1<=nums.length<=104
104<=nums[i]<=104
nums 为 无重复元素 的 升序 排列数组
104<=target<=104

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        if(nums[0]>=target){
            return 0;
        }
        int l=0,r=nums.size()-1,ans=0;
        while(r>=l){
            int mid=(l+r)/2;
            if(nums[mid]<target){
               ans=mid; 
               l=mid+1;
            }
            else{
                r=mid-1;
            }
            
        }    
        return ans+1;
    }
};
int searchInsert(int* nums, int numsSize, int target){
    int left=0,right=numsSize-1;
    while(left<=right){
        int mid=(left+right)/2;
        if(nums[mid]==target)
            return mid;
        else if(nums[mid]>target)
            right=mid-1;
        else if(nums[mid]<target)
            left=mid+1;

    }
    return left;
}

寻找比目标字母大的最小字母

给你一个字符数组letters,该数组按非递减顺序排序,以及一个字符target,letters里至少有两个不同的字符。

返回letters中大于target的最小的字符。如果不存在这样的字符,则返回letters的第一个字符。

示例 1:
输入: letters = ["c", "f", "j"],target = "a"
输出: "c"
解释:letters 中字典上比 'a' 大的最小字符是 'c'。

示例 2:
输入: letters = ["c","f","j"], target = "c"
输出: "f"
解释:letters 中字典顺序上大于 'c' 的最小字符是 'f'。

示例 3:
输入: letters = ["x","x","y","y"], target = "z"
输出: "x"
解释:letters 中没有一个字符在字典上大于 'z',所以我们返回 letters[0]。

提示:
2<=letters.length<=104
letters[i] 是一个小写字母
letters 按非递减顺序排序
letters 最少包含两个不同的字母
target 是一个小写字母

class Solution {
public:
    char nextGreatestLetter(vector<char>& letters, char target) {
        int l=0,r=letters.size()-1,ans=0;
        while(r>=l){
            int mid=(l+r)/2;
            if(letters[mid]>target){
                r=mid-1;
                ans=mid;
            }
            else{
                l=mid+1;
            }
        }
        return letters[ans];
    }
};

统计有序矩阵中的负数

给你一个m×n的矩阵grid,矩阵中的元素无论是按行还是按列,都以非递增顺序排列。 请你统计并返回grid中 负数 的数目。

示例 1:
输入:grid = [[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]]
输出:8
解释:矩阵中共有 8 个负数。

示例 2:
输入:grid = [[3,2],[1,0]]
输出:0

提示:

m == grid.length
n == grid[i].length
1 <= m, n <= 100
-100 <= grid[i][j] <= 100

class Solution {
public:
    int countNegatives(vector<vector<int>>& grid) {
        int ans=0;
        int n=grid.size();
        int m=grid[0].size();
        for(int i=0;i<n;i++){
            int l=0,r=m-1,res=m;
            while(r>=l){
                int mid=(l+r)/2;
                if(grid[i][mid]<0){
                    r=mid-1;
                    res=mid;
                }
                else{
                    l=mid+1;
                }
            }
            ans+=abs(m-res); 
        }
        return ans;
    }
    
};

寻找右区间

给你一个区间数组intervals,其中intervals[i]=[starti,endi],且每个starti都 不同 。

区间i的 右侧区间 可以记作区间j,并满足startj>=endi,且startj最小化 。注意i可能等于j

返回一个由每个区间i右侧区间intervals中对应下标组成的数组。如果某个区间i不存在对应的 右侧区间 ,则下标i处的值设为1

示例 1:
输入:intervals = [[1,2]]
输出:[-1]
解释:集合中只有一个区间,所以输出-1。

示例 2:
输入:intervals = [[3,4],[2,3],[1,2]]
输出:[-1,0,1]
解释:对于 [3,4] ,没有满足条件的“右侧”区间。
对于 [2,3] ,区间[3,4]具有最小的“右”起点;
对于 [1,2] ,区间[2,3]具有最小的“右”起点。

示例 3:
输入:intervals = [[1,4],[2,3],[3,4]]
输出:[-1,2,-1]
解释:对于区间 [1,4] 和 [3,4] ,没有满足条件的“右侧”区间。
对于 [2,3] ,区间 [3,4] 有最小的“右”起点。

提示:
1<=intervals.length<=2104
intervals[i].length == 2
106<=starti<=endi<=106
每个间隔的起点都 不相同
这个题就是按照starti,排序之后然后再按照endi二分查找就行

class Solution {
public:
    vector<int> findRightInterval(vector<vector<int>>& intervals) {
        vector<int>ans;
        vector<vector<int>> a=intervals;
        int n=intervals.size();
        map<int,int>mp;
        for(int i=0;i<n;i++){
            mp[intervals[i][0]]=i;
        }
        sort(a.begin(),a.end());
        for(int i=0;i<n;i++){
           // cout<<a[i][0]<<" "<<a[i][1]<<endl;
            int l=0,r=n-1,res=-1;
            while(r>=l){//1 3 4 5
                int mid=(l+r)/2;
                if(a[mid][0]>=a[i][1]){
                    r=mid-1;
                    res=mid;
                }
                else{
                    l=mid+1;
                }
            }
            ans.push_back(res);
        }
        vector<int>v(n);
        for(int i=0;i<n;i++){
            if(ans[i]==-1){
                v[mp[a[i][0]]]=-1;
            }
            else{
                v[mp[a[i][0]]]=mp[a[ans[i]][0]];
            }
        }
        return v;
    }
};
posted @   lipu123  阅读(5)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
历史上的今天:
2020-11-11 素数阶乘取余—(威尔逊定理)
2020-11-11 快速乘法+快速幂
2020-11-11 线段树维护连续区间
点击右上角即可分享
微信分享提示