1、二分法
二分法,需要注意mid 的取值,以及while中的等于号
1.1、搜索查找位置
public int searchInsert(int[] nums, int target) {
int low = 0, high = nums.length - 1;
int mid;
while (low <= high) {
mid = low + (high-low)/2;
// System.out.println("a -- mid:" +(low+ (low + high) / 2));
// System.out.println("b -- mid:" + (mid));
if (nums[mid]>=target) high = mid - 1;
else low = mid + 1;
}
return low;
}
在上述中的数组中如果存在数字会直接返回结果,在while中可以不加等于号,当数组中不存在时,最后一次循环结果low = right ,且 mid = low 因此也可改造成下列程序:
//简单的二分查找
if (nums == null || nums.length == 0) {
return 0;
}
//小知识点: java数组的最大长度为int的最大值
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = (left + right) / 2;
if (target == nums[mid]) {
return mid;
} else if (target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
//此时left = right
return target <= nums[left] ? left : left + 1;
}
1.2、搜索二维矩阵
常规方法:分两次,分别是对列和行分别用二分法查找
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length, n = matrix[0].length;
boolean res = false;
int low = -1,high = m-1; //左开右闭的原则
while (low < high) {
int mid = low + (high - low+1) / 2;
if (matrix[mid][0]<=target) low= mid;
else high=mid-1;
}
if(low<0) return false;
System.out.println(low);
int left = 0, right = n - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (matrix[low][mid]<target) left = mid + 1;
else if (matrix[low][mid]>target) right = mid - 1;
else return true;
}
return res;
}
一次拼接法:根据数组性质,将每一行的末尾与下一行进行拼接 并且将下标映射到原矩阵的行与列上
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length, n = matrix[0].length;
int low = 0, high = m * n - 1;
while (low <= high) {
int mid = (high - low) / 2 + low;
int x = matrix[mid / n][mid % n]; //下标映射
if (x < target) {
low = mid + 1;
} else if (x > target) {
high = mid - 1;
} else {
return true;
}
}
return false;
}
}
1.3、在排序数组中查找元素的第一个和最后一个位置
可以直接套用二分法查找模板,当找到目标元素时,进行左右遍历,找到边界
public int[] searchRange(int[] nums, int target) {
int[] res = new int[]{-1, -1};
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (target == nums[mid]) {
left = mid;
// System.out.println(mid);
while (mid>=0 && nums[mid] == target) {
mid--;
}
res[0] = mid + 1;
while (left<nums.length && nums[left] == target) {
left++;
}
res[1] = left - 1;
return res;
} else if (target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return res;
}
左右分别求解
···java