5月7日 - 二分法

二分法 Binary Search   Given a sorted integer array - nums, and an integer - target, find the any/first/last position of target in nums.  Return -1 if target does not exist.

O(1)极少

O(logn)   二分法

O(n)  大部分

O(nlogn)  排序

O(n^2)  数组 动态规划

是否使用递归   递归的函数深度

二分法模板

1、start + 1 < end

2、start + (end - start) / 2

3、A[mid]==, <, >

4、A[start]  A[end]  target

  如果写成start < end,除以2一般向左靠,可能产生死循环。      中间的循环不断缩小,直到你用眼睛看,用手数就能找到结果。

1、经典二分查找问题

在一个排序数组中找一个数,返回该数出现的任意位置,如果不存在,返回-1

public class Solution {
    /*
     * @param nums: An integer array sorted in ascending order
     * @param target: An integer
     * @return: An integer
     */
    public int findPosition(int[] nums, int target) {
        // write your code here
        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 if (nums[mid] > target) { end = mid; } } if (nums[start] == target) return start; if (nums[end] == target) return end; return -1; } }

2、给定一个排序的整数数组(升序)和一个要查找的整数target,用O(logn)的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1

 第一个错误代码的版本(类似第一个满足条件的下标)   要考虑if...else...的条件判断,能解决问题就行,无需多次调用判断函数 SVNRepo.isBadVersion(),以免超时。

/**
 * public class SVNRepo {
 *     public static boolean isBadVersion(int k);
 * }
 * you can use SVNRepo.isBadVersion(k) to judge whether 
 * the kth code version is bad or not.
*/

public class Solution {
    /*
     * @param n: An integer
     * @return: An integer which is the first bad version.
     */
    public int findFirstBadVersion(int n) {
        // write your code here
        int start = 1, end = n;
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (SVNRepo.isBadVersion(mid)) {
                end = mid;
            } else {
                start = mid;
            }
        }
        if (SVNRepo.isBadVersion(start)) {
            return start;
        } 
        return end;
    }
}

3、

假设一个旋转排序的数组其起始位置是未知的(比如0 1 2 4 5 6 7 可能变成是4 5 6 7 0 1 2)。

你需要找到其中最小的元素。

你可以假设数组中不存在重复的元素。

Ans:很自然想到要用O(logn)解法 -> 二分,即first position <= last number

非有序怎么解决?若last < mid,最小在右;若last > mid,最小在左或本位;

特殊情况,nums[start] < nums[end],直接返回首位,减少计算时间

public class Solution {
    /**
     * @param nums: a rotated sorted array
     * @return: the minimum number in the array
     */
    public int findMin(int[] nums) {
        // write your code here
        int start = 0, end = nums.length - 1;
        if (nums[start] < nums[end]) {
            return nums[start];
        }
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (nums[mid] < nums[end]) {
                end = mid;
            } else {
                start = mid;
            }
        }
        if (nums[start] < nums[end]) {
            return nums[start];
        } else {
            return nums[end];
        }
    }
}

4、

Write an efficient algorithm that searches for a value in an m x n matrix.

This matrix has the following properties:

  • Integers in each row are sorted from left to right.
  • The first integer of each row is greater than the last integer of the previous row.  一定要注意数组判断是否为null或者数组长度为0。
public class Solution {
    /**
     * @param matrix: matrix, a list of lists of integers
     * @param target: An integer
     * @return: a boolean, indicate whether matrix contains target
     */
    public boolean searchMatrix(int[][] matrix, int target) {
        // write your code here
        if (matrix == null || matrix.length == 0) {
            return false;
        }
        if (matrix[0] == null || matrix[0].length == 0) {
            return false;
        }
        int m = matrix.length;
        int n = matrix[0].length;
        int start = 0, end = m * n - 1;
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            int temp = matrix[mid / n][mid % n];
            if (temp == target) {
                return true;
            } else if (temp < target) {
                start = mid;
            } else {
                end = mid;
            }
        }
        if (matrix[start / n][start % n] == target || matrix[end / n][end % n] == target) {
            return true;
        } else {
            return false;
        }
    }
}

5、

Given a sorted array of n integers, find the starting and ending position of a given target value.

If the target is not found in the array, return [-1, -1].   注意return new int[]{-1, -1};

public class Solution {
    /**
     * @param A: an integer sorted array
     * @param target: an integer to be inserted
     * @return: a list of length 2, [index1, index2]
     */
    public int[] searchRange(int[] A, int target) {
        // write your code here
        if (A == null || A.length == 0) {
            return new int[]{-1, -1};
        }
        int start = 0, end = A.length - 1;
        int firstIndex = -1, endIndex = -1;
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (A[mid] == target) {
                end = mid;
            } else if (A[mid] > target) {
                end = mid;
            } else {
                start = mid;
            }
        }
        if (A[start] == target) {
            firstIndex = start;
        } else if (A[end] == target) {
            firstIndex = end;
        } else {
            return new int[]{-1, -1};
        }
        endIndex = firstIndex;
        while (endIndex <= A.length - 1) {
            if (A[endIndex] != target) {
                break;
            }
            endIndex++;
        }
        return new int[]{firstIndex, endIndex-1};
    }
}

猜你喜欢

转载自www.cnblogs.com/li-ling/p/8911761.html