【必备算法】二分查找:LeetCode题(二)33. 搜索旋转排序数组,240. 搜索二维矩阵 II

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])开始找:

    1. 如果 target < [i][j],行不变,列左移
    2. 如果 target > [i][j],列不变,行下移
    3. 相等则返回
  • 复杂度:

    • 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;
    }

猜你喜欢

转载自blog.csdn.net/weixin_43935927/article/details/114109714