Leetcode刷题系列(二)Binary Search

Binary Search的基础框架代码

Bianry Search的基本思想

  二分查找法是基于一组有序数上的查找,它的时间复杂度最坏为O(n),平均时间复杂度为O(lgn),空间复杂度为O(1)。由于它不需要借助额外的空间,并且大多数情况下(平均)性能较好,所以是应用较广的一种查找法。
  接下来介绍一些其他查找方法的时间和空间复杂度:

查找算法 平均时间复杂度 最坏时间复杂度 空间复杂度
顺序查找 O(n) O(n) O(1)
二分查找 O(lgn) O(n) O(1)
二叉树查找 O(lgn) O(lgn) O(n)
哈希查找 O(1) O(1) O(n)

  二叉树查找需要在原有数据的基础上建立二叉排序树,因此需要额外的空间,比较适合多次连续查找。类似的算法有哈希查找,需要额外空间建立哈希表,同时考虑冲突处理等问题。
  可以看出,二叉查找是比较适合不知道查找次数的情况。因为他不需要建立额外储存结构。

Bianry Search的基础框架代码

  该代码为实现在有序数组中查找某个目标数的基本框架,与二叉查找有关的其他题型可在此框架上进行修改。
  

    public int findPosition(int[] nums, int target) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        int start = 0, end = nums.length - 1;
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                start = mid;
            } else {
                end = mid;
            }
        }
        if (nums[start] == target) {
            return start;
        }
        if (nums[end] == target) {
            return end;
        }
        return -1;
    }

  该代码搜索位置比较偏左,搜索到的目标数可能的第一个位置为start。

Binary Search的相关题型

Search Insert Position

  题目为搜索目标数第一个出现的位置,如果找不到则返回其应该插入的位置。

  换种思路可以有:搜索源数组里第一个大于等于目标数的位置,或者最后一个小于目标数的位置+1。这两种思想需要充分利用start和end的位置关系。

Search a 2D Matrix I

  题目为在一个二维数组中搜索目标数。

  解题思路有以下两种:

  • 由于二维数组里的数是严格递增的,因此可以将二维数组看成一维数组进行搜索,每个数的下标可以看成是i×n+j。使用matrix[mid / column][mid % column]与目标数进行对比。
  • 可以先搜索行,再搜索列。注意搜索行的时候,去寻找第一个小于等于matrix[mid][0]的数,该数所在的行数即为所要找的行数。因此,退出循环之后要先与matrix[end][0]进行对比。

Search a 2D Matrix II

  题目为写出一个高效的算法来搜索m×n矩阵中的值,返回这个值出现的次数。这个矩阵具有以下特性:

  • 每行中的整数从左到右是排序的。
  • 每一列的整数从上到下是排序的。
  • 在每一行或每一列中没有重复的整数。

      该二维数组中的数并不是严格递增的,因此不适合上题中的方法。但其可以看成是是在二维坐标轴中进行向右或向上的行走。即初始时在左下角逐渐向右上角进行搜索。代码片段:

     while (x >= 0 && y < m) {
            if (matrix[x][y] < target) {
                y++;
            } else if (matrix[x][y] > target) {
                x--;
            } else {
                count++;
                x--;
                y++;
            }
        }

Find Peak Element

  题目为返回任意一个峰值的位置。因此,应使A[mid]与A[mid + 1]和A[mid - 1]进行比较,最后的结果在A[start]和A[end]之间,所以还需要进行最后一次判断,返回较大者。

First Bad Version

  该题需要返回第一个错误的版本,要求调用次数较少。调用次数可以看成比较次数,某种意义上说也是时间复杂度,因此使用二分查找很合适。使用上述框架,则可以考虑成寻找第一个位置上的SVNRepo.isBadVersion(mid)为ture的值。

你可能感兴趣的:(leetcode)