class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int m=matrix.length;
int n=matrix[0].length;
int size=m*n;
int left=0;
int right=size-1;
while(left <=right){
int mid= (left+right)/2;
if(matrix[mid/n][mid%n]==target){
return true;
}else if(matrix[mid/n][mid%n]<target){
left=mid+1;
}else{
right=mid-1;
}
}
return false;
}
}
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int rowIndex = binarySearchFirstColumn(matrix, target);
if (rowIndex < 0) {
return false;
}
return binarySearchRow(matrix[rowIndex], target);
}
public int binarySearchFirstColumn(int[][] matrix, int target) {
int low = -1, high = matrix.length - 1;
while (low < high) {
int mid = (high - low + 1) / 2 + low;
if (matrix[mid][0] <= target) {
low = mid;
} else {
high = mid - 1;
}
}
return low;
}
public boolean binarySearchRow(int[] row, int target) {
int low = 0, high = row.length - 1;
while (low <= high) {
int mid = (high - low) / 2 + low;
if (row[mid] == target) {
return true;
} else if (row[mid] > target) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return false;
}
}
class Solution {
public int findPeakElement(int[] nums) {
int idx = 0;
for (int i = 1; i < nums.length; ++i) {
if (nums[i] > nums[idx]) {
idx = i;
}
}
return idx;
}
}
class Solution {
public int findPeakElement(int[] nums) {
int left=0;
int right=nums.length-1;
while(left <=right){
int mid=(left+right)/2;
if(compare(nums,mid-1, mid)<0 && compare(nums,mid,mid+1)>0){
return mid;
}
if(compare(nums,mid,mid+1)<0){
left=mid+1;
}else{
right=mid-1;
}
}
return -1;
}
private int compare(int[] nums, int index1, int index2){
if(index1==-1){
return -1;
}
if(index2==nums.length){
return 1;
}
if(nums[index1] ==nums[index2]){
return 0;
}
return nums[index1] > nums[index2] ? 1 : -1;
}
}
class Solution {
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;
}
}
class Solution {
// 两次二分查找,分开查找第一个和最后一个
// 时间复杂度 O(log n), 空间复杂度 O(1)
// [1,2,3,3,3,3,4,5,9]
public int[] searchRange(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
int first = -1;
int last = -1;
// 找第一个等于target的位置
while (left <= right) {
int middle = (left + right) / 2;
if (nums[middle] == target) {
first = middle;
right = middle - 1; //重点
} else if (nums[middle] > target) {
right = middle - 1;
} else {
left = middle + 1;
}
}
// 最后一个等于target的位置
left = 0;
right = nums.length - 1;
while (left <= right) {
int middle = (left + right) / 2;
if (nums[middle] == target) {
last = middle;
left = middle + 1; //重点
} else if (nums[middle] > target) {
right = middle - 1;
} else {
left = middle + 1;
}
}
return new int[]{first, last};
}
}
class Solution {
// 两次二分查找,分开查找第一个和最后一个
// 时间复杂度 O(log n), 空间复杂度 O(1)
// [1,2,3,3,3,3,4,5,9]
public int[] searchRange(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
int first = -1;
int last = -1;
// 找第一个等于target的位置
while (left <= right) {
int middle = (left + right) / 2;
if (nums[middle] < target) {
left = middle + 1;
} else {
right = middle - 1;
}
}
//边界条件
if(left<nums.length && nums[left]==target){
first=left;
}
// 最后一个等于target的位置
left = 0;
right = nums.length - 1;
while (left <= right) {
int middle = (left + right) / 2;
if (nums[middle] <= target) {
left = middle + 1;
} else {
right = middle - 1;
}
}
//边界条件
if(right>=0 && nums[right]==target){
last=right;
}
return new int[]{first, last};
}
}
class Solution {
public int findMin(int[] nums) {
int low = 0;
int high = nums.length - 1;
while (low < high) {
int pivot = (high +low) / 2;
if (nums[pivot] < nums[high]) {
high = pivot;
} else {
low = pivot+1;
}
}
return nums[high];
}
}
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int n = nums1.length;
int m = nums2.length;
//找到第K小的数
int left = (n + m + 1) / 2;
int right = (n + m + 2) / 2;
//将偶数和奇数的情况合并,如果是奇数,会求两次同样的 k 。
return (getKth(nums1, 0, n - 1, nums2, 0, m - 1, left) + getKth(nums1, 0, n - 1, nums2, 0, m - 1, right)) * 0.5;
}
private int getKth(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k) {
int len1 = end1 - start1 + 1;
int len2 = end2 - start2 + 1;
//让 len1 的长度小于 len2,这样就能保证如果有数组空了,一定是 len1
if (len1 > len2) return getKth(nums2, start2, end2, nums1, start1, end1, k);
if (len1 == 0) return nums2[start2 + k - 1];
if (k == 1) return Math.min(nums1[start1], nums2[start2]);
//找到 A[k/2−1]和B[k/2−1]的位置
int i = start1 + Math.min(len1, k / 2) - 1;
int j = start2 + Math.min(len2, k / 2) - 1;
if (nums1[i] > nums2[j]) {
//如果 A[k/2−1]>B[k/2−1],则可以排除 B[0] 到 B[k/2−1]
return getKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1));
}else {
//排除A[0] 到 A[k/2−1]
return getKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1));
}
}
}
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
// 如果 nums1 的长度大于 nums2 的长度,则调换两个数组,确保 nums1 是较短的数组
if (nums1.length > nums2.length) {
return findMedianSortedArrays(nums2, nums1);
}
int m = nums1.length;
int n = nums2.length;
int left = 0, right = m;
// median1:前一部分的最大值
// median2:后一部分的最小值
int median1 = 0, median2 = 0;
// 使用二分查找确定分割点
while (left <= right) {
// 前一部分包含 nums1[0 .. i-1] 和 nums2[0 .. j-1]
// 后一部分包含 nums1[i .. m-1] 和 nums2[j .. n-1]
int i = (left + right) / 2;
int j = (m + n + 1) / 2 - i;
// 获取有序数组 nums1 和 nums2 中当前分割点的相邻元素值
int nums1LeftMax = (i == 0 ? Integer.MIN_VALUE : nums1[i - 1]);
int nums1RightMin = (i == m ? Integer.MAX_VALUE : nums1[i]);
int nums2LeftMax = (j == 0 ? Integer.MIN_VALUE : nums2[j - 1]);
int nums2RightMin = (j == n ? Integer.MAX_VALUE : nums2[j]);
if (nums1LeftMax <= nums2RightMin) {
median1 = Math.max(nums1LeftMax, nums2LeftMax);
median2 = Math.min(nums1RightMin, nums2RightMin);
left = i + 1; // 移动左边界
} else {
right = i - 1; // 移动右边界
}
}
// 根据奇偶情况返回中位数
return (m + n) % 2 == 0 ? (median1 + median2) / 2.0 : median1;
}
}