package top100.二分法;
public class TOP {
//35. 搜索插入位置
public int searchInsert(int[] nums, int target) {
int n = nums.length;
int left = 0, right = n - 1;
while (left <= right) { //当left==mid,搜索到最后一个数字
int mid = left + (right - left) / 2;
if (target > nums[mid]) {
left = mid + 1;
} else if (target < nums[mid]) {
right = mid - 1;
} else {
return mid;
}
}
return left;
}
//74. 搜索二维矩阵
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length;
int n = matrix[0].length;
int i = m - 1, j = 0;
while (i >= 0 && j <= n - 1) {
if (matrix[i][j] == target) {
return true;
} else if (matrix[i][j] > target) {
i--;
} else {
j++;
}
}
return false;
}
//34. 在排序数组中查找元素的第一个和最后一个位置
public int[] searchRange(int[] nums, int target) {
int left = 0, right = nums.length - 1;
int[] res = new int[2];
res[0] = -1;
res[1] = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (target == nums[mid]) {
left = mid - 1;
//向左搜索第一个
while (left >= 0 && nums[left] == nums[mid]) {
left--;
}
res[0] = left + 1;
right = mid + 1;
//向右搜索最后一个
while (right <= nums.length - 1 && nums[right] == nums[mid]) {
right++;
}
res[1] = right - 1;
break;
} else if (target > nums[mid]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return res;
}
//33. 搜索旋转排序数组
//方法1:将数组分为两段升序数组,用二分法搜索
//方法2:先判断是在左段还是在右端,在判断target在mid的左边还是右边
public int search(int[] nums, int target) {
if (nums.length == 0) return -1;
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (target == nums[mid]) return mid;
//mid在左段:left到mid肯定是升序
if (nums[left] <= nums[mid]) {
//target在left和mid之间
if (target >= nums[left] && target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
} else { //mid在右段:mid到right肯定是升序
if (target > nums[mid] && target <= nums[right] ) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}
//153. 寻找旋转排序数组中的最小值
public int findMin(int[] nums) {
int left = 0, right = nums.length - 1;
while (left < right) { //目标在left和right之间
int mid = left + (right - left) / 2;
//只能比较mid和right的值才能确定min的位置
if (nums[mid] > nums[right]) { //最小值肯定在右边
left = mid + 1;
} else if (nums[mid] < nums[right]) { //最小值可能是mid
right = mid;
}
}
return nums[left];
}
//4. 寻找两个正序数组的中位数
//这题可以转化为,如何找到第k小的元素
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length, n = nums2.length;
int total = m + n;
if (total % 2 == 1) { //奇数,寻找第k小
int k = total / 2 + 1;
return findKth(nums1, nums2, k);
} else { //寻找第k小和第k+1小
int k = total / 2;
int a = findKth(nums1, nums2, k);
int b = findKth(nums1, nums2, k + 1);
return (a + b) * 1.0 / 2;
}
}
private int findKth(int[] nums1, int[] nums2, int k) {
int m = nums1.length, n = nums2.length;
int start1 = 0, start2 = 0; //数组有效不能的起点索引
while (true) {
//处理特殊情况
if (start1 == m) { //数组1越界,直接返回数组2的第k小数字
return nums2[start2 + k - 1];
}
if (start2 == n) {
return nums1[start1 + k - 1];
}
//寻找第1小
if (k == 1) {
return Math.min(nums1[start1], nums2[start2]);
}
//开始排除第k小前面的数据
int half = k / 2;
int index1 = Math.min(start1 + half, m) - 1;//如果half超出数组,用最后一位数字
int index2 = Math.min(start2 + half, n) - 1;
//比较nums1[k/2-1]和nums2[k/2-1]
if (nums1[index1] > nums2[index2]) {
k -= (index2 - start2 + 1); //先更新k
start2 = index2 + 1; //忽略掉num2的half个元素
} else {
k -= (index1 - start1 + 1);
start1 = index1 + 1;
}
}
}
}
LeetCode算法练习top100:(8)二分法
最新推荐文章于 2024-11-09 20:38:27 发布