题目:
Given a sorted array of integers, find the starting and ending position of a given target value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1]
.
For example,
Given [5, 7, 7, 8, 8, 10]
and target value 8,
return [3, 4]
.
链接: http://leetcode.com/problems/search-for-a-range/
题解:
考察Binary Search的结束条件。 使用两次Bianry Search,一次搜索左边界,一次搜索右边界,最后需要比较一下左边界是否 <= 右边界,假如条件不成立则target不在数组中。
Time Complexity - O(n), Space Complexity - O(1)
public class Solution { public int[] searchRange(int[] nums, int target) { int[] res = {-1, -1}; if(nums == null || nums.length == 0) return res; int lolo = 0, lohi = nums.length - 1, hilo = 0, hihi = nums.length - 1; while(lolo <= lohi) { //try find left end int mid = lolo + (lohi - lolo) / 2; if(nums[mid] < target) lolo = mid + 1; else lohi = mid - 1; } while(hilo <= hihi) { //try find right end int mid = hilo + (hihi - hilo) / 2; if(nums[mid] > target) hihi = mid - 1; else hilo = mid + 1; } if(lolo <= hihi) { //if target exist res[0] = lolo; res[1] = hihi; } return res; } }
二刷:
Java:
要使用两次binary search来分别搜索target值的最左端和最右端。最后需要判断一下求出来的left 是否<= right,否则 [1], 1这样的test case会过不了
public class Solution { public int[] searchRange(int[] nums, int target) { int[] res = {-1, -1}; if (nums == null || nums.length == 0) { return res; } int lo = 0, hi = nums.length - 1; while (lo <= hi) { int mid = lo + (hi - lo) / 2; if (target > nums[mid]) { lo = mid + 1; } else { hi = mid - 1; } } int left = lo; lo = 0; hi = nums.length - 1; while (lo <= hi) { int mid = lo + (hi - lo) / 2; if (target >= nums[mid]) { lo = mid + 1; } else { hi = mid - 1; } } int right = hi; if (left <= right) { res[0] = left; res[1] = right; } return res; } }
三刷:
这回写得比较奇怪。原理都一样,都是使用两次binary search,但是改变了一些变量和条件。
要注意搜索左边界时,遇到mid = target时我们hi = mid - 1,最后返回的边界index是lo。搜索右边界时,遇到mid = target我们lo = mid + 1,最后返回的边界index是hi。也需要判断一下没有搜索到的case,这就是代码里的两个独立if语句的作用。
Java:
public class Solution { public int[] searchRange(int[] nums, int target) { int[] res = {-1, -1}; if (nums == null) return res; int lo = 0, hi = nums.length - 1; while (lo <= hi) { int mid = lo + (hi - lo) / 2; if (nums[mid] < target) lo = mid + 1; else hi = mid - 1; } if (lo > nums.length - 1 || nums[lo] != target) return new int[] {-1, -1}; res[0] = lo; lo = 0; hi = nums.length - 1; while (lo <= hi) { int mid = lo + (hi - lo) / 2; if (nums[mid] > target) hi = mid - 1; else lo = mid + 1; } if (hi < 0 || nums[hi] != target) return new int[] {-1, -1}; res[1] = hi; return res; } }
Update:
public class Solution { public int[] searchRange(int[] nums, int target) { int[] res = {-1, -1}; if (nums == null) return res; int lo = 0, hi = nums.length - 1; while (lo <= hi) { int mid = lo + (hi - lo) / 2; if (nums[mid] < target) lo = mid + 1; else hi = mid - 1; } if (lo > nums.length - 1 || nums[lo] != target) return res; res[0] = lo; hi = nums.length - 1; while (lo <= hi) { int mid = lo + (hi - lo) / 2; if (nums[mid] > target) hi = mid - 1; else lo = mid + 1; } res[1] = hi; return res; } }