二分法 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) 二分法spa
O(n) 大部分code
O(nlogn) 排序blog
O(n^2) 數組 動態規劃排序
是否使用遞歸 遞歸的函數深度遞歸
二分法模板ci
一、start + 1 < endget
二、start + (end - start) / 2it
三、A[mid]==, <, >
四、A[start] A[end] target
若是寫成start < end,除以2通常向左靠,可能產生死循環。 中間的循環不斷縮小,直到你用眼睛看,用手數就能找到結果。
一、經典二分查找問題
在一個排序數組中找一個數,返回該數出現的任意位置,若是不存在,返回-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; } }
二、給定一個排序的整數數組(升序)和一個要查找的整數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; } }
三、
假設一個旋轉排序的數組其起始位置是未知的(好比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]; } } }
四、
Write an efficient algorithm that searches for a value in an m x n matrix.
This matrix has the following properties:
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; } } }
五、
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}; } }