初步认识二分查找[小汇总]

声明:小白总结,本意是记录自己的思路,不过希望能帮助别人,那就更好啦,若发现问题,欢迎指正,感谢!!

来源:力扣(LeetCode)
链接:704.二分查找

题目:二分查找

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

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

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

题目解析

这个题目呢,可以说可以深刻理解二分的含义了,我认为就是每次分两半,一直一直……直到找到目标值
首先要知道数组的长度吧,然后呢,要有两个位置指针,循环终止条件是两指针相遇,当然啦,写法有很多,理解之后可以自己试试新的写法,我只是个小白……太弱了

代码
// java
class Solution {
    public int search(int[] nums, int target) {
        int m = nums.length;//数组长度
        int left = 0, right = m - 1;//两个位置指针
        while(left < right){//终止条件:两指针相遇
        //找到中间位置,这样写是比较不容易出错的
            int mid = left + (right - left) / 2;
            if(nums[mid] < target){//如果中间值比目标值小
                left = mid + 1;//往右移
            }else{
                right = mid;//否则,往左移
            }
        }
        //最后left == right
        如果此时的值(也可以用nums[right])与目标值相同,找到啦~否则,没找到……
        return nums[left] == target ? left : -1;
    }
}

——————————————
要再来个二分小宝贝吗?

Yes
——————————————
来源:力扣(LeetCode)
链接:374.猜数字大小

题目:猜数字大小

我们正在玩一个猜数字游戏。 游戏规则如下:
我从 1 到 n 选择一个数字。 你需要猜我选择了哪个数字。
每次你猜错了,我会告诉你这个数字是大了还是小了。
你调用一个预先定义好的接口 guess(int num),它会返回 3 个可能的结果(-1,1 或 0):
-1 : 我的数字比较小
1 : 我的数字比较大
0 : 恭喜!你猜对了!

输入: n = 10, pick = 6
输出: 6

题目解析

这个题目跟上面一题可以说是基本一样啦,只不过这里直接给了一个接口值让我们来比较大小,想一下之后来看吧

代码
// java
/** 
 * Forward declaration of guess API.
 * @param  num   your guess
 * @return 	     -1 if num is lower than the guess number
 *			      1 if num is higher than the guess number
 *               otherwise return 0
 * int guess(int num);
 */

public class Solution extends GuessGame {
    public int guessNumber(int n) {
        int left = 1, right = n;//两个指针
        while(left <= right){//while(left < right)//循环条件
            int mid = left + (right - left) / 2;//中间值
            if(guess(mid) == 0){//找到目标值
                return mid;//返回
            }else if(guess(mid) == -1)//目标值较小
                right = mid;//往左移
            }else{//否则
                left = mid + 1;//往右移
            }
        }
        return -1;//return left//返回
    }
}

——————————————
要再来个二分小宝贝吗?

Yes
——————————————

来源:力扣(LeetCode)
链接:面试题11.旋转数组的最小数字

题目:旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转
输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素
例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。

输入:[3,4,5,1,2]
输出:1

输入:[2,2,2,0,1]
输出:0

题目解析

这个问题是想要找到那个旋转的值,可以想一下,这个旋转的最小值有什么特点呢,可以看到,它前面的值比最后一个值大,而它后面的值小于等于最后一个值,查找时就可以利用这个特性,这是如何确定的呢,我也是有迷惑,来记录一下,一个值如果比最后的大,那么它一定在前面的递增部分,目标值当然在它的后面啦,如果比最后的要小,那么它在后面的递增部分,那么目标值一定在他前面啦,这样一直缩小搜查范围,只要有,就一定会抓到哒~
因为有重复值的原因,我们要考虑,也就是说我们可能会遇到一个值跟最后一个值相同,由于这个数组是有序的,所以可以考虑把它砍掉,让这个二分再分一会儿
总结一下:先找到目标值的特点,来做排查,再将重复值砍掉
——————————应该就是这样啦~

代码
// java
class Solution {
    public int minArray(int[] numbers){
        int m = numbers.length;//数组长度
        int left = 0, right = m - 1;//两个指针
        while(left < right){//循环条件
            int mid = left + (right - left) / 2;//中间值
            if(numbers[mid] > numbers[right]){
            //比最后值大,往右分
                left = mid + 1;
            }else if(numbers[mid] < numbers[right]){
            //比最后值小,往左分
                right = mid;
            }else{
                right--;//重复,砍掉
            }
        }
        return numbers[left];//返回目标值
    }
}

——————————————
要再来个二分小宝贝吗?

Yes
——————————————

来源:力扣(LeetCode)
链接:面试题53 - I. 在排序数组中查找数字 I

题目: 在排序数组中查找数字 I

统计一个数字在排序数组中出现的次数。

输入: nums = [5,7,7,8,8,10], target = 8
输出: 2

输入: nums = [5,7,7,8,8,10], target = 6
输出: 0
限制:
0 <= 数组长度 <= 50000

题目解析

题目要求我们找目标值出现的次数,如果我们能找到第一个出现的目标值,然后向后遍历并计数,就可得到,怎么找到第一个目标值就是我们的首要问题了。利用这个方法也可以解决找目标值首位置以及尾位置的问题。
现在来解决找到首个目标值的问题,二分法就是一直二分,直到找到目标值,首先,我们在解决二分查找时,可以说num[mid]的值很可能就目标值,如果我们把与目标值相同的mid趋向于往左边分,那么我们找到的是不是就是第一个了呢
比如:

while(left < right){
     if(num[left] > target){
            left = mid + 1;
     }else{
            right = mid;//把相同值往左分
     }
}

再比如:

while(left < right){
     if(num[left] < target){
            right = mid;
     }else{
            left = mid + 1;//把相同值往右分
     }
}
代码
// java
class Solution {
    public int search(int[] nums, int target) {
        int n = nums.length;
        if(nums == null || n == 0) return 0;
        int left = 0;
        int right = n - 1;
        while(left < right){
            int mid = left + (right - left)/2;
            if(nums[mid] < target){
                left = mid + 1;
            }else{
                right = mid;//将相同值往左分,得到第一个目标值
            }
        }
        int res = 0;
        //将前提条件写在前面,防止数组越界
        while((left <= n - 1) && (left >= 0) && (nums[left] == target)){
            res++;//记录目标值个数
            left++;//右移
        }
        return res;
    }
}

——————————————
要再来个二分小宝贝吗?

Yes
——————————————

来源:力扣(LeetCode)
链接:349. 两个数组的交集

题目:两个数组的交集

给定两个数组,编写一个函数来计算它们的交集。

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2]

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [9,4]
说明:
输出结果中的每个元素一定是唯一的。
我们可以不考虑输出结果的顺序。

题目解析

这一题要找他们的交集,也就是说两个数组都有的元素,不考虑顺序,但不能重复
我们可以先固定一个数组,然后在另一个数组中查找,查到时要考虑,这个数是否已经存在了
思路不是很难,来实现吧

代码
// java
class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
    //定义一个Set数组来排查是否重复
        Set<Integer> set = new HashSet<>();
        Arrays.sort(nums2);//给小2排序
        for(int target : nums1){//遍历小1的每个数
        //看看在小2中能不能找到它,然后Set中有它了嘛~
            if(binarySearch(nums2, target) && !set.contains(target)){
                set.add(target);//满足条件,加入大家庭吧
            }
        }
        int index = 0;//小朋友,排队拿票啦
        int[] res = new int[set.size()];//定义一个数组房子
        for(int num : set){//看看都有哪些小朋友
            res[index++] = num;//按顺序进来玩吧
        }
        return res;//返回结果
    }
    //就用它来看看小1中的数在不在小2中
    private boolean binarySearch(int[] nums, int target){
        int left = 0, right = nums.length - 1;//两个指针
        while(left <= right){//循环条件
            int mid = left + (right - left) / 2;//中间值
            if(nums[mid] == target){//找到啦
                return true;//有它
            }else if(nums[mid] < target){//比中间值大?
                left = mid + 1;//右移
            }else{//比中间值小?
                right = mid - 1;//左移
            }
        }
        //不可以在外面判断nums[left] == target
        //万一小2是空心怎么办~越界啦~ 所以把它放里面判断吧
        return false;//没找到那就是没有啦~
    }
}

感谢各位巨巨们的帮助,希望在记录分析题目的条件下算法能有所提升……
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值