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

📢📢📢📣📣📣
哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10年DBA工作经验
一位上进心十足的【大数据领域博主】!😜😜😜
中国DBA联盟(ACDU)成员,目前从事DBA及程序编程
擅长主流数据Oracle、MySQL、PG 运维开发,备份恢复,安装迁移,性能优化、故障应急处理等。
✨ 如果有对【数据库】感兴趣的【小可爱】,欢迎关注【IT邦德】💞💞💞
❤️❤️❤️感谢各位大可爱小可爱!❤️❤️❤️

前言

算法是程序员的内功,掌握算法不仅能帮助你在面试中过关斩将,赢取 Dream Offer,更能充分锻炼你的逻辑思维与底层能力,我是一名忠实的 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. 答案

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;
    }
}

在这里插入图片描述

🚀 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;
    }
}

在这里插入图片描述

🚀 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;
    }
}

在这里插入图片描述

🚀 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. 答案

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;
    }
}

在这里插入图片描述

🚀 367. 有效的完全平方数

🌈 1. 题目

给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。
进阶:不要 使用任何内置的库函数,如  sqrt 。


示例 1:
输入:num = 16
输出:true

示例 2:
输入:num = 14
输出:false
 
提示:
1 <= num <= 2^31 - 1

🌈 2. 答案

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;        
    }
}

在这里插入图片描述

🚀 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);
    }
}

在这里插入图片描述

🚀 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;
    }
}

在这里插入图片描述

🚀 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];
    }
}

在这里插入图片描述

备战秋招,LeetCode算法大总结,啃下这块硬骨头
https://jeames.blog.csdn.net/article/details/124919920

在这里插入图片描述

  • 5
    点赞
  • 2
    收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:代码科技 设计师:Amelia_0503 返回首页
评论 4

打赏作者

IT邦德

客户部署资料,步骤超详细

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值