題目連接數組
題目大意:找出一串升序數組中target值的起始下標和結束下標值,若是不存在則返回{-1,-1}。ide
解法一:用二分查找,找到數組中的target,而後找其左邊和右邊的target下標值。代碼以下(耗時11ms):spa
1 public int[] searchRange(int[] nums, int target) { 2 if(nums == null || nums.length == 0) { 3 int[] r = {-1, -1}; 4 return r; 5 } 6 int low = 0, high = nums.length - 1; 7 int start = -1, end = -1; 8 while(low <= high) { 9 int mid = (low + high) / 2; 10 if(nums[mid] < target) { 11 low = mid + 1; 12 } 13 else if(nums[mid] > target) { 14 high = mid - 1; 15 } 16 else { 17 //找左邊起始下標 18 for(int i = mid; i >= 0; i--) { 19 if(nums[i] == target) { 20 start = i; 21 } 22 else { 23 break; 24 } 25 } 26 //找右邊終止下標 27 for(int i = mid; i < nums.length; i++) { 28 if(nums[i] == target) { 29 end = i; 30 } 31 else { 32 break; 33 } 34 } 35 break; 36 } 37 } 38 int[] res = {start, end}; 39 return res; 40 }
解法二:直接暴力,一次遍歷,找重複值。代碼以下(耗時10ms):code
1 public int[] searchRange(int[] nums, int target) { 2 int start = -1, end = -1; 3 boolean mark = false; 4 for(int i = 0; i < nums.length; i++) { 5 if(nums[i] == target) { 6 if(mark == false) { 7 start = end = i; 8 mark = true; 9 } 10 else { 11 end = i; 12 } 13 } 14 } 15 int[] res = {start, end}; 16 return res; 17 }
解法三:真正的二分查找。法一其實複雜度仍是o(n)。應該先對起始下標進行二分查找,而後再對結束下標進行二分查找。代碼以下(耗時5ms):blog
1 public int[] searchRange(int[] nums, int target) { 2 int left = 0, right = nums.length - 1; 3 int[] res = {-1, -1}; 4 if(nums.length == 0) { 5 return res; 6 } 7 //二分找到起始下標 8 while(left < right) { 9 int mid = (left + right) / 2; 10 //這裏比較左值,若是<,則left更新,不然left不會更新 11 //因此left不更新有兩種狀況:>或= 12 if(nums[mid] < target) { 13 left = mid + 1; 14 } 15 //這裏通通修改右值 16 else { 17 right = mid; 18 } 19 } 20 if(nums[left] != target) { 21 return res; 22 } 23 res[0] = left; 24 left = 0; 25 right = nums.length - 1; 26 //二分找到結束下標 27 while(left < right) { 28 //這裏要+1,不然會出錯 29 int mid = (left + right) / 2 + 1; 30 //比較右值,若是>,則right更新 31 if(nums[mid] > target) { 32 right = mid - 1; 33 } 34 //修改Left 35 else { 36 left = mid; 37 } 38 } 39 res[1] = right; 40 return res; 41 }