3.29 二分查找

This commit is contained in:
zhangsan 2025-03-29 20:07:56 +08:00
parent c85a5023f1
commit a41a72c55b
4 changed files with 215 additions and 0 deletions

View File

@ -0,0 +1,47 @@
package binary_search;
/**
* 题目 33. 搜索旋转排序数组 (searchRange)
* 描述整数数组 nums 按升序排列数组中的值 互不相同
* 在传递给函数之前nums 在预先未知的某个下标 k0 <= k < nums.length上进行了 旋转使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]下标 0 开始 计数例如 [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2]
* 给你 旋转后 的数组 nums 和一个整数 target 如果 nums 中存在这个目标值 target 则返回它的下标否则返回 -1
* 你必须设计一个时间复杂度为 O(log n) 的算法解决此问题
* 示例 1
输入nums = [4,5,6,7,0,1,2], target = 0
输出4
* 链接https://leetcode.cn/problems/search-in-rotated-sorted-array/
*/
//不会
public class Search {
public int search(int[] nums, int target) {
int n = nums.length;
if (n == 0) {
return -1;
}
if (n == 1) {
return nums[0] == target ? 0 : -1;
}
int l = 0, r = n - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (nums[mid] == target) {
return mid;
}
if (nums[0] <= nums[mid]) {
if (nums[0] <= target && target < nums[mid]) {
r = mid - 1;
} else {
l = mid + 1;
}
} else {
if (nums[mid] < target && target <= nums[n - 1]) {
l = mid + 1;
} else {
r = mid - 1;
}
}
}
return -1;
}
}

View File

@ -0,0 +1,48 @@
package binary_search;
/**
* 题目 35. 搜索插入位置 (floodFill)
* 描述给定一个排序数组和一个目标值在数组中找到目标值并返回其索引如果目标值不存在于数组中返回它将会被按顺序插入的位置
* 请必须使用时间复杂度为 O(log n) 的算法
*
* 示例 1
输入: nums = [1,3,5,6], target = 5
输出: 2
* 链接https://leetcode.cn/problems/search-insert-position/
*/
//第一道二分法的题不熟练
public class SearchInsert {
public int searchInsert(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = (right + left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
}
private int helper(int[] nums, int target, int left, int right) {
if (left > right) {
return left;
}
int mid = (right + left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
return helper(nums, target, mid + 1, right);
} else {
return helper(nums, target, left, mid - 1);
}
}
public int searchInsert1(int[] nums, int target) {
return helper(nums, target, 0, nums.length - 1);
}
}

View File

@ -0,0 +1,32 @@
package binary_search;
/**
* 题目 74. 搜索二维矩阵 (searchMatrix)
* 描述给你一个满足下述两条属性的 m x n 整数矩阵
*
* 每行中的整数从左到右按非严格递增顺序排列
* 每行的第一个整数大于前一行的最后一个整数
* 给你一个整数 target 如果 target 在矩阵中返回 true 否则返回 false
*
* 示例 1
输入matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出true
* 链接https://leetcode.cn/problems/search-a-2d-matrix/
*/
public class SearchMatrix {
public boolean searchMatrix(int[][] matrix, int target) {
int r=matrix.length;
int c=matrix[0].length;
int i=0,j=c-1;
while (i<=r-1 && j>=0){
if(target==matrix[i][j])
return true;
else if(target>matrix[i][j])
i++;
else
j--;
}
return false;
}
}

View File

@ -0,0 +1,88 @@
package binary_search;
/**
* 题目 34. 在排序数组中查找元素的第一个和最后一个位置 (searchRange)
* 描述给你一个按照非递减顺序排列的整数数组 nums和一个目标值 target请你找出给定目标值在数组中的开始位置和结束位置
* 如果数组中不存在目标值 target返回 [-1, -1]
* 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题
* 示例 1
输入nums = [5,7,7,8,8,10], target = 8
输出[3,4]
* 链接https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/
*/
public class SearchRange {
//极端情况下不是O(log n)
public int[] searchRange(int[] nums, int target) {
int left=0,right=nums.length-1;
int tpleft=-1,tpright=-1;
while (left<=right){
int mid=(left+right)/2;
if(target==nums[mid]){
tpleft=mid-1;
tpright=mid+1;
while (tpleft>=left) {
if (target == nums[tpleft])
tpleft--;
else
break;
}
tpleft++;
while (tpright<=right) {
if (target == nums[tpright])
tpright++;
else
break;
}
tpright--;
break;
}
else if(target>nums[mid])
left=mid+1;
else
right=mid-1;
}
return new int[]{tpleft,tpright};
}
private int findLeft(int[] nums, int target) {
int left = 0, right = nums.length - 1;
int index = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] >= target) {
right = mid - 1;
} else {
left = mid + 1;
}
if (nums[mid] == target) {
index = mid;
}
}
return index;
}
// 找到目标值的最后一次出现位置
private int findRight(int[] nums, int target) {
int left = 0, right = nums.length - 1;
int index = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] <= target) {
left = mid + 1;
} else {
right = mid - 1;
}
if (nums[mid] == target) {
index = mid;
}
}
return index;
}
public int[] searchRange1(int[] nums, int target) {
int leftIndex = findLeft(nums, target);
int rightIndex = findRight(nums, target);
return new int[]{leftIndex, rightIndex};
}
}