33. 搜索旋转排序数组²
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7]
可能变为 [4,5,6,7,0,1,2]
)。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1
。
你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。
示例 1:
输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4
示例 2:
输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1
解法:二分查找
- 思路:要求了O(logn),相当于说明了要二分查找;但是对于此题不能直接二分查找,在判断区间时要分成有序边和无序边来处理
- 复杂度
- Time:O(logn)
- Sapce:O(1)
public int search(int[] nums, int target) {
if (nums == null || 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; // 找到了
// 左边有序,右边无序(可能)
// 比如[4,5,6,7,0,1],所以arr[left]<arr[mid],即左边[4,5,6]有序,右边[7,0,1]无序
if (nums[left] <= nums[mid]) {
// 照理说只用判断target < nums[mid]就行。但看上例,如果target=0就判断错了,所以还要 target>=nums[left]
if (target < nums[mid] && target >= nums[left]) right = mid - 1;
else left = mid + 1;
// 右边有序,左边无序(可能)
}else {
if (target > nums[mid] && target <= nums[right]) left = mid + 1;
else right = mid - 1;
}
}
return -1;
}
240. 搜索二维矩阵 II²
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:
- 每行的元素从左到右升序排列。
- 每列的元素从上到下升序排列。
示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5
,返回 true
。
给定 target = 20
,返回 false
。
解法一:暴力迭代
- 思路:没啥说的,就是遍历二维数组
- 复杂度:
- Time:O(n * m)
- Space:O(1)
public boolean searchMatrix(int[][] matrix, int target) {
// 遍历二维数组时,可以理解为数组的数组
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
if (matrix[i][j] == target) return true;
}
}
return false;
}
解法二:二分查找
-
思路:有规律排列的查找问题 -----> 二分查找。本题与之前习题不一样之处就在于是一个二维数组,怎么办呢?从右上角(
[0][j-1]
)开始找:- 如果 target <
[i][j]
,行不变,列左移 - 如果 target >
[i][j]
,列不变,行下移 - 相等则返回
- 如果 target <
-
复杂度:
- Time:O(m + n)
- Space:O(1)
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix.length == 0 || matrix[0].length == 0) return false;
int m = matrix.length, n = matrix[0].length;
// 得到右上角位置,i行j列
int i = 0, j = n - 1;
while (i < m && j >= 0) {
if (target < matrix[i][j]) j--; // 左移
else if (target > matrix[i][j]) i++; // 下移
else return true;
}
return false;
}