二分查找
前置知识:无
定义:他利用数据的有序性,每轮缩小一半的搜索范围,直到找到目标元素或搜索区间为空为止。
基本思想:在有序列表中,每次都取中间值作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若其小于中间值,则在中间值以左进行查找;反之,在中间值以右进行查找。不断重复上面的过程,直到找到目标元素或搜索区间为空为止。
二分查找的几种情况分析
- 有序数组中确定num值是否存在
public static int binarySearch(int[] arr, int target){
int l = 0;
int r = arr.length - 1;
int m = 0;
while(l <= r){
m = (l + r) / 2;
if(arr[m] < target){
l = m + 1;
}
if(arr[m] > target){
r = m -1;
}
else {
return m;
}
}
return -1;
}
2.在有序数组中找>=num的最左位置
public static int findLeft(int[] arr, int target) {
int l = 0, r = arr.length - 1;
int ans = -1;
while(l <= r) {
int m = (l + r) / 2;
if(arr[m] < target) {
l = m + 1;
}else {
ans = m;
r = m - 1;
}
}
return ans;
}
3.在有序数组中找<=num的最右位置
public static int findRight(int[] arr, int target) {
int l = 0, r = arr.length - 1;
int ans = -1;
while(l <= r) {
int m = (l + r) / 2;
if(arr[m] > target){
r = m - 1;
} else {
ans = m;
l = m + 1;
}
}
return ans;
}
二分之美~!
你真的理解二分吗???
题目2:https://leetcode.cn/problems/nth-magical-number/description/
package class002;
/**
* ClassName: Code02_NthMagicalNumber
* Package: class002
* Description:
*
* @Author 华因斯坦
* @Create 2025/4/17 8:40
* @Version 1.0
*/
public class Code02_NthMagicalNumber {
public static long gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
public static long lcm(int a, int b) {
return a / gcd(a, b) * b;
}
public static int nthMagicalNumber(int n, int a, int b) {
long lcm = lcm(a, b);
long l = 0, r = (long)n * Math.min(a, b);
long mid = 0;
long ans = 0;
while(l <= r) {
mid = l + ((r - l) >> 1);
if(mid / a + mid / b - mid / lcm >= n) {
ans = mid;
l = mid + 1;
}else {
r = mid -1;
}
}
return (int)(ans % 1000000007);
}
public static void main(String[] args) {
int n = 4, a = 2, b = 3;
System.out.println(nthMagicalNumber(n, a, b));
}
}
难道二分查找只能在有序数组中出现吗???
题目2:https://leetcode.cn/problems/find-peak-element/
package class002;
/**
* ClassName: FindPeakElement
* Package: class002
* Description:
*
* @Author 华因斯坦
* @Create 2025/4/16 21:50
* @Version 1.0
*/
// |--->法一(自己写的):
public class FindPeakElement {
public static int findPeakElement(int[] nums) {
if(nums.length == 1) return 0;
int l = 0, r = nums.length - 1;
int mid = 0;
if(nums[l] > nums[l + 1]) return l;
if(nums[r] > nums[r - 1]) return r;
while(l <= r) {
mid = l + ((r - l) >> 1);
if(mid == 0) {
mid = 1;
} else if (mid == nums.length - 1) {
mid = nums.length - 2;
}
if(nums[mid] > nums[mid - 1]){
if(nums[mid] > nums[mid + 1]){
return mid;
}else{
l = mid + 1;
continue;
}
} else {
r = mid - 1;
}
}
return -1;
}
}
// |--->法二(大神写的):
public class FindPeakElement {
public static int findPeakElement(int[] arr) {
int n = arr.length;
if (arr.length == 1) {
return 0;
}
if (arr[0] > arr[1]) {
return 0;
}
if (arr[n - 1] > arr[n - 2]) {
return n - 1;
}
// 这里与我写的不同,但是比我更好(慢慢体会,慢慢从题目中去分析吧)
int l = 1, r = n - 2, m = 0, ans = -1;
while (l <= r) {
m = (l + r) / 2;
if (arr[m - 1] > arr[m]) {
r = m - 1;
} else if (arr[m] < arr[m + 1]) {
l = m + 1;
} else {
ans = m;
break;
}
}
return ans;
}
}
3093

被折叠的 条评论
为什么被折叠?



