点击跳转到题目位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
提示:
class Solution {
public int searchInsert(int[] nums, int target) {
int ans = -1;
int left = 0;
int right = nums.length - 1;
while(left <= right){
int mid = ((left + right) >> 1);
if(nums[mid] == target){
ans = mid;
break;
} else if(nums[mid] < target){
left = mid + 1;
} else{
ans = mid;
right = mid - 1;
}
}
if(ans == -1){
ans = nums.length;
}
return ans;
}
}
1, 二分查找经典模板题目。
点击跳转到题目位置
给你一个满足下述两条属性的 m x n 整数矩阵:
给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false 。
提示:
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length;
int n = matrix[0].length;
int left = 0;
int right = m - 1;
int row = -1;
while(left <= right){
int mid = ((left + right) >> 1);
if(matrix[mid][0] == target){
return true;
} else if(matrix[mid][0] < target){
row = mid;
left = mid + 1;
} else{
right = mid - 1;
}
}
if(row == -1){
return false;
}
left = 0;
right = n - 1;
while(left <= right){
int mid = ((left + right) >> 1);
if(matrix[row][mid] == target){
return true;
} else if(matrix[row][mid] < target){
left = mid + 1;
} else{
right = mid - 1;
}
}
return false;
}
}
点击跳转到题目位置
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
提示:
class Solution {
// 找到等于target的最小下标
public int search1(int[] nums, int target){
int n = nums.length;
int left = 0;
int right = n - 1;
int ans = -1;
while(left <= right){
int mid = ((left + right) >> 1);
if(nums[mid] > target){
right = mid - 1;
} else if(nums[mid] == target){
right = mid - 1;
ans = mid;
} else{
left = mid + 1;
}
}
return ans;
}
// 找到等于target的最大下标
public int search2(int[] nums, int target){
int n = nums.length;
int left = 0;
int right = n - 1;
int ans = -1;
while(left <= right){
int mid = ((left + right) >> 1);
if(nums[mid] > target){
right = mid - 1;
} else if(nums[mid] == target){
left = mid + 1;
ans = mid;
} else{
left = mid + 1;
}
}
return ans;
}
public int[] searchRange(int[] nums, int target) {
int ans1 = search1(nums, target);
int ans2 = search2(nums, target);
return new int[]{ans1, ans2};
}
}
点击跳转到题目位置
整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= 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) 的算法解决此问题。
提示:
class Solution {
public int search(int[] nums, int target) {
int n = nums.length;
int left = 0;
int right = n - 1;
int ans = -1;
while(left <= right){
int mid = ((left + right) >> 1);
if(nums[mid] == target){
ans = mid;
break;
}
// 下面确定哪一片区域是有序的
if(nums[mid] < nums[0]){ // 右侧是有序的
if(target < nums[0] && target >= nums[mid]){
left = mid + 1;
} else{
right = mid - 1;
}
} else{ // 左侧是有序的
if(target >= nums[0] && target < nums[mid]){
right = mid - 1;
} else{
left = mid + 1;
}
}
}
return ans;
}
}
点击跳转到题目位置
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
提示:
class Solution {
public int findMin(int[] nums) {
int n = nums.length;
int left = 0;
int right = n - 1;
int ans = nums[0];
while(left <= right){
int mid = ((left + right) >> 1);
if(nums[mid] >= nums[0]){ // 往右侧找即可(因为最小的数初始化就是最左边的数)
left = mid + 1;
} else{
ans = Math.min(ans, nums[mid]);
right = mid - 1;
}
}
return ans;
}
}
点击跳转到题目位置
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
提示:
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
int len = m + n;
if((len & 1) == 1){
int idx = len / 2;
return getKthElement(nums1, nums2, idx + 1); // 获取第idx + 1小的元素
} else{
int idx = len / 2;
return (getKthElement(nums1, nums2, idx) + getKthElement(nums1, nums2, idx + 1)) / 2.0;
}
}
public int getKthElement(int[] nums1, int[] nums2, int k){// 获取第k小的元素
int m = nums1.length;
int n = nums2.length;
int idx1 = 0;
int idx2 = 0;
while(true){
if(idx1 == m){
return nums2[idx2 + k - 1];
}
if(idx2 == n){
return nums1[idx1 + k - 1];
}
if(k == 1){
return Math.min(nums1[idx1], nums2[idx2]);
}
int half = k / 2;
int newIdx1 = Math.min(idx1 + half, m) - 1;
int newIdx2 = Math.min(idx2 + half, n) - 1;
int num1 = nums1[newIdx1];
int num2 = nums2[newIdx2];
if(num1 <= num2){
k -= (newIdx1 - idx1 + 1);
idx1 = newIdx1 + 1;
} else{
k -= (newIdx2 - idx2 + 1);
idx2 = newIdx2 + 1;
}
}
}
}