【LeetCode-算法专栏】二分查找

简介: 【LeetCode-算法专栏】二分查找

🚀 704. 二分查找


🌈 1. 题目


给定一个 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]之间。


🌈 2. 答案

eff51de768cf49eeb53a724f436d57aa.png

class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length;
        while (left < right) {
            int mid = left + ((right - left) >> 1);
            if (nums[mid] == target)
                return mid;
            else if (nums[mid] < target)
                left = mid + 1;
            else if (nums[mid] > target)
                right = mid;
        }
        return -1;
    }
}


eff51de768cf49eeb53a724f436d57aa.png


🚀 374. 猜数字大小


🌈 1. 题目


猜数字游戏的规则如下:
每轮游戏,我都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。
如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。
你可以通过调用一个预先定义好的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0):
-1:我选出的数字比你猜的数字小 pick < num
1:我选出的数字比你猜的数字大 pick > num
0:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num
返回我选出的数字。
示例 1:
输入:n = 10, pick = 6
输出:6
示例 2:
输入:n = 1, pick = 1
输出:1
示例 3:
输入:n = 2, pick = 1
输出:1
示例 4:
输入:n = 2, pick = 2
输出:2
提示:
1 <= n <= 231 - 1
1 <= pick <= n


🌈 2. 答案


public class Solution extends GuessGame {
    public int guessNumber(int n) {
        int l = 1, r = n, m, t;
        while (l <= r) {
            m = (r - l) / 2 + l;
            t = guess(m);
            if (t == 0) {
                return m;
            } else if (t < 0) {
                r = m - 1;
            } else {
                l = m + 1;
            }
        }
        return l;
    }
}


4f863985de254f3d96b5cff20d6e9065.png

🚀 35. 搜索插入位置


给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例 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


🌈 2. 答案


class Solution {
    public int searchInsert(int[] nums, int target) {
        int n = nums.length;
        // 定义target在左闭右闭的区间,[low, high]
        int low = 0;
        int high = n - 1;
        while (low <= high) { // 当low==high,区间[low, high]依然有效
            int mid = low + (high - low) / 2; // 防止溢出
            if (nums[mid] > target) {
                high = mid - 1; // target 在左区间,所以[low, mid - 1]
            } else if (nums[mid] < target) {
                low = mid + 1; // target 在右区间,所以[mid + 1, high]
            } else {
                // 1. 目标值等于数组中某一个元素  return mid;
                return mid;
            }
        }
        // 2.目标值在数组所有元素之前 3.目标值插入数组中 4.目标值在数组所有元素之后 return right + 1;
        return high + 1;
    }
}


fda02e5b12904938837df48ea684efb2.png

🚀 852. 山脉数组的峰顶索引


🌈 1. 题目


符合下列属性的数组 arr 称为 山脉数组 :
arr.length >= 3
存在 i(0 < i < arr.length - 1)使得:
arr[0] < arr[1] < ... arr[i-1] < arr[i]
arr[i] > arr[i+1] > ... > arr[arr.length - 1]
给你由整数组成的山脉数组 arr ,返回任何满足 arr[0] < arr[1] < ... arr[i - 1] < arr[i] > arr[i + 1] > ... > arr[arr.length - 1] 的下标 i 。
示例 1:
输入:arr = [0,1,0]
输出:1
示例 2:
输入:arr = [0,2,1,0]
输出:1
示例 3:
输入:arr = [0,10,5,2]
输出:1
示例 4:
输入:arr = [3,4,5,1]
输出:2
示例 5:
输入:arr = [24,69,100,99,79,78,67,36,26,19]
输出:2
提示:
3 <= arr.length <= 104
0 <= arr[i] <= 106
题目数据保证 arr 是一个山脉数组
进阶:很容易想到时间复杂度 O(n) 的解决方案,你可以设计一个 O(log(n)) 的解决方案吗?


🌈 2. 答案

a6cf4a765fd144b7a679826cd00d5d13.png

class Solution {
    public int peakIndexInMountainArray(int[] arr) {
        //二分法,先选择左右两下标。
       int left=0;
       int right=arr.length-1;
      int mid=0;
        while(left<right){
            mid=left+(right-left)/2;
            //左右都小于mid,说明mid是山峰。
            if(arr[mid-1]<arr[mid]&& arr[mid]>arr[mid+1]) break;
            //右边比左边高,说明山峰在右侧
            if(arr[mid+1]>arr[mid]) left=mid;
            //右边比左边低,山峰在左侧
            else if(arr[mid+1]<arr[mid]) right=mid;
        }
        return mid;
    }
}


a6cf4a765fd144b7a679826cd00d5d13.png


🚀 367. 有效的完全平方数


🌈 1. 题目


给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。
进阶:不要 使用任何内置的库函数,如  sqrt 。
示例 1:
输入:num = 16
输出:true
示例 2:
输入:num = 14
输出:false
提示:
1 <= num <= 2^31 - 1


🌈 2. 答案

1a628158f89a4e6e842742392babcbb5.png

class Solution {
    public boolean isPerfectSquare(int num) {
        int i = 1, j = num;       
        while(i <= j){
            int mid = i + (j - i) / 2;
            long y = (long)mid * mid;
            if(y == num) return true;
            if(y < num) i = mid + 1;
            else j = mid - 1;
            }
        return false;        
    }
}


1a628158f89a4e6e842742392babcbb5.png


🚀 1385. 两个数组间的距离值


🌈 1. 题目


给你两个整数数组 arr1 , arr2 和一个整数 d ,请你返回两个数组之间的 距离值 。
「距离值」 定义为符合此距离要求的元素数目:对于元素 arr1[i] ,不存在任何元素 arr2[j] 满足 |arr1[i]-arr2[j]| <= d 。
示例 1:
输入:arr1 = [4,5,8], arr2 = [10,9,1,8], d = 2
输出:2
解释:
对于 arr1[0]=4 我们有:
|4-10|=6 > d=2 
|4-9|=5 > d=2 
|4-1|=3 > d=2 
|4-8|=4 > d=2 
所以 arr1[0]=4 符合距离要求
对于 arr1[1]=5 我们有:
|5-10|=5 > d=2 
|5-9|=4 > d=2 
|5-1|=4 > d=2 
|5-8|=3 > d=2
所以 arr1[1]=5 也符合距离要求
对于 arr1[2]=8 我们有:
|8-10|=2 <= d=2
|8-9|=1 <= d=2
|8-1|=7 > d=2
|8-8|=0 <= d=2
存在距离小于等于 2 的情况,不符合距离要求 
故而只有 arr1[0]=4 和 arr1[1]=5 两个符合距离要求,距离值为 2
示例 2:
输入:arr1 = [1,4,2,3], arr2 = [-4,-3,6,10,20,30], d = 3
输出:2
示例 3:
输入:arr1 = [2,1,100,3], arr2 = [-5,-2,10,-3,7], d = 6
输出:1
提示:
1 <= arr1.length, arr2.length <= 500
-10^3 <= arr1[i], arr2[j] <= 10^3
0 <= d <= 100


🌈 2. 答案


class Solution {
    public int findTheDistanceValue(int[] arr1, int[] arr2, int d) {
        //双指针法
        int index1 = 0, n = arr1.length;
        int index2 = 0, m = arr2.length;
        int res = 0;
        Arrays.sort(arr1);
        Arrays.sort(arr2);
        while(index1 < n && index2 < m) {
            if(arr1[index1] > arr2[index2] + d) index2 ++;
            else if(arr1[index1] + d < arr2[index2]) index1 ++;
            else {
                res ++;
                index1 ++;
            }
        }
        return (n-index1)+(index1-res);
    }
}


b6138e21f8c7493a9d8e7418f72fdb10.png


🚀 69. x 的平方根


🌈 1. 题目


给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
示例 1:
输入:x = 4
输出:2
示例 2:
输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
提示:
0 <= x <= 231 - 1


🌈 2. 答案


class Solution {
    public int mySqrt(int x) {
        long left = 0, mid, right = x;
        while(left<=right) {
            mid = left + (right - left)/2;
            if(x < mid*mid) {
                right = mid - 1;
            } else if(x > mid*mid) {
                left = mid + 1;
            } else {
                return (int)mid;
            }
        }
        return (int)right;
    }
}

6ec4096dc18a4e5f87a27b9f1d13f008.png

🚀 744. 寻找比目标字母大的最小字母


🌈 1. 题目


给你一个排序后的字符列表 letters ,列表中只包含小写英文字母。另给出一个目标字母 target,请你寻找在这一有序列表里比目标字母大的最小字母。
在比较时,字母是依序循环出现的。举个例子:
如果目标字母 target = 'z' 并且字符列表为 letters = ['a', 'b'],则答案返回 'a'
示例 1:
输入: letters = ["c", "f", "j"],target = "a"
输出: "c"
示例 2:
输入: letters = ["c","f","j"], target = "c"
输出: "f"
示例 3:
输入: letters = ["c","f","j"], target = "d"
输出: "f"
提示:
2 <= letters.length <= 104
letters[i] 是一个小写字母
letters 按非递减顺序排序
letters 最少包含两个不同的字母
target 是一个小写字母


🌈 2. 答案


class Solution {
    public char nextGreatestLetter(char[] letters, char target) {
        int left = 0;
        int right = letters.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (letters[mid] - target > 0) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return letters[left % letters.length];
    }
}


ece9394cedcf4359ac1aa437bf20c0f9.png


目录
相关文章
|
1月前
|
算法
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
|
28天前
|
算法
测试工程师的技能升级:LeetCode算法挑战与职业成长
这篇文章通过作者亲身体验LeetCode算法题的过程,探讨了测试工程师学习算法的重要性,并强调了算法技能对于测试职业成长的必要性。
42 1
测试工程师的技能升级:LeetCode算法挑战与职业成长
|
1月前
|
存储 算法 Java
深入算法基础二分查找数组
文章深入学习了二分查找算法的基础,通过实战例子详细解释了算法的逻辑流程,强调了确定合法搜索边界的重要性,并提供了Java语言的代码实现。
深入算法基础二分查找数组
|
1月前
|
算法 Java
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
36 6
|
1月前
|
存储 算法 Java
LeetCode经典算法题:打家劫舍java详解
LeetCode经典算法题:打家劫舍java详解
46 2
|
1月前
|
人工智能 算法 Java
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
37 1
|
1月前
|
存储 算法 Java
LeetCode经典算法题:预测赢家+香槟塔java解法
LeetCode经典算法题:预测赢家+香槟塔java解法
35 1
|
1月前
|
算法
【算法】二分查找——二分查找
【算法】二分查找——二分查找
|
1月前
|
存储 算法 Java
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
60 0
|
1月前
|
算法 Java
LeetCode初级算法题:子数组最大平均数+二叉树的最小深度+最长连续递增序列+柠檬水找零
LeetCode初级算法题:子数组最大平均数+二叉树的最小深度+最长连续递增序列+柠檬水找零
32 0