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