首页 > 其他分享 >【LeetCode】704.二分查找

【LeetCode】704.二分查找

时间:2023-05-28 10:31:54浏览次数:53  
标签:二分 right nums 704 左闭 middle int LeetCode left

704.二分查找

image-20230507201945552

解析:

思路一:暴力解法,直接遍历,从头开始查找,如果找到直接返回下标,找不到返回-1。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        for(int i = 0; i < nums.size(); i++)
        {
            if(nums[i] == target)
                return i;
        }
        return -1;
    }
};

思路二:二分查找;

使用二分查找的前提条件是:

1.数组为有序数组;

2.数组中无重复元素(一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的)。

二分查找中,最容易搞混的两点为:

1.while循环里面的条件应该是while(left < right)还是while(left <= right)

2.right再次赋值的时候应该是right = middle还是right = middle - 1

二分查找分析:

首先我们要对区间的定义进行明确,即确定这个区间是左闭右闭([left,right],区间包含leftright)还是左闭右开([left,right),区间包含left,但是不包含right),一般情况下都是这两种情况;然后针对不同区间的定义,进行边界条件的处理(即while循环条件)。

对于区间的定义不一样,是直接影响边界条件的处理的(即while循环条件)。

第一种情况:左闭右闭

当我们使用左闭右闭区间的时候,while(left <= right)是合法的,即leftright能够满足这个条件;

right再次赋值时我们已经判断middle不等于target了,要控制好边界条件,所以要让right = middle-1;当我们写成right = middle时,区间不明确,边界处理的不对,会出问题;left再次赋值时,也不能等于middle,更新右区间里的左边界。

image-20230508095335989

左闭右闭代码如下:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int right = nums.size() - 1; //左闭右闭要包含right,所以right = nums.size() - 1
        int left = 0;
        while(left <= right) //合法情况
        {
            int middle = (left + right) / 2;
            if(nums[middle] > target)
                right = middle - 1;//更新左区间里的右边界
            else if(nums[middle] < target)
                left = middle + 1;//更新右区间里的左边界
            else
                return middle;
        }
        return -1;
    }
};

第二种情况:左闭右开

左闭右开区间,left不能和right相等,所以循环条件应该是while(left < right),根据区间的定义来查询,因为右开不包含right,所以right = middle,更新左区间里的右边界,left更新的时候仍然是left = middle + 1

image-20230508095349062

左闭右开代码如下:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int right = nums.size();//左闭右开不包含right,所以right = nums.size()
        int left = 0;
        while(left < right) //不能加等于
        {
            int middle = (left + right) / 2;
            if(nums[middle] > target)
                right = middle;//更新左区间里的右边界
            else if(nums[middle] < target)
                left = middle + 1;//更新右区间里的左边界
            else
                return middle;
        }
        return -1;
    }
};

总结:

左闭右闭区间时,while的循环条件为left <= right,且right = middle -1

左闭右开区间时,while的循环条件为left < right,且right = middle

两个区间的left都是left = middle + 1

标签:二分,right,nums,704,左闭,middle,int,LeetCode,left
From: https://blog.51cto.com/u_15562309/6364871

相关文章

  • 力扣 662 https://leetcode.cn/problems/maximum-width-of-binary-tree/
    需要了解树的顺序存储如果是普通的二叉树,底层是用链表去连接的如果是满二叉树,底层用的是数组去放的,而数组放的时候会有索引对应当前父节点是索引i,下一个左右节点就是2i,2i+1利用满二叉树的索引特征所以需要对每个节点进行一个索引赋值,赋值在队列中,队列用数组表示核心代码......
  • leetcode: 有效的括号
    题目描述给定一个只包括'(',')','{','}','[',']' 的字符串s,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型的左括号。示例1:输入:"()"输出:true示例2:输入:"()[]{}"输......
  • 二分图和 2-SAT 问题入门
    二分图定义通俗的说,就是一个图可以分成两个部分,两个部分内部没有连接的边,所有的边都在两个部分之间。比如这就是一张二分图。可以发现,A,B集合中各自是没有边连接的,边都连在了AB集合之间。并且4是独立的,所以其实我们把它归到集合A中或者集合B中都可以。判断二分图就......
  • 【LeetCode】203. 移除链表元素
    203.移除链表元素思路一:直接删除法(迭代)1.从头结点开始向后遍历,找到等于val的结点;2.假设cur->val=val,那么要让cur的前一个结点prev的next指针指向cur的下一个结点,即prev->next=cur->next。要注意的是当头结点的值等于val时(head->val=val),因为头节点没有前一个结点,所以可......
  • LeetCode 114. 二叉树展开为链表
    思路1classSolution{public:voidflatten(TreeNode*root){while(root){autop=root->left;if(p)//找到左儿子的右链{while(p->right)p=p->right;//将右链插入......
  • hdu:第K小的数(构造二分)
    ProblemDescription给定\(n\)个正整数\(a_1,a_2,\dots,a_n\)和\(m\)个正整数\(b_1,b_2,\dots,b_m\)。请在\(n\timesm\)个\(a_i+b_j(1\leqi\leqn,1\leqj\leqm)\)中,找到第\(k\)小的数(不去重)。Input第一行包含一个正整数\(T(1\leqT\leq10)\),表示测试数据的组数。每组......
  • #yyds干货盘点# LeetCode程序员面试金典:二叉树展开为链表
    题目:给你二叉树的根结点root,请你将它展开为一个单链表:展开后的单链表应该同样使用TreeNode,其中right子指针指向链表中下一个结点,而左子指针始终为null。展开后的单链表应该与二叉树先序遍历顺序相同。 示例1:输入:root=[1,2,5,3,4,null,6]输出:[1,null,2,null,3,null,4,......
  • hdu:Ice Cream Tower(构造二分)
    一座高度为k的塔\(b1,b_2,\dots,b_k\)满足\(2b_1\leqb_2,2b_2\leqb_3,2b_3\leqb_4,\dots,2b{k-1}\leqb_k\)你要从中选择一些数来叠很多座高度为\(k\)的塔,问最多能叠多少座塔。Input第一行包含一个正整数T(1≤T≤10),表示测试数据的组数。每组数据第一行包含两个正整数n,k(2......
  • hdu:序列划分(构造二分)
    ProblemDescription给定\(n\)个正整数\(a_1,a_2,\dots,a_n\),将这个序列从左到右划分成\(m\)段,使得每段至少有一个数。你需要让数字之和最大的那一段的数字和尽可能得小。Input第一行包含一个正整数T(1≤T≤10),表示测试数据的组数。每组数据第一行包含两个正整数n,m(1≤m≤......
  • #yyds干货盘点# LeetCode程序员面试金典:路径总和 II
    题目:给你二叉树的根节点root和一个整数目标和targetSum,找出所有从根节点到叶子节点路径总和等于给定目标和的路径。叶子节点是指没有子节点的节点。 示例1:输入:root=[5,4,8,11,null,13,4,7,2,null,null,5,1],targetSum=22输出:[[5,4,11,2],[5,8,4,5]]示例2:输入:root=......