力扣刷题日常#34
1 class Solution { 2 public int[] searchRange(int[] nums, int target) { 3 int[] res = {-1 , -1}; 4 int len = nums.length; 5 for(int i = 0; i < len; i++){ 6 if(nums[i] == target){ 7 res[0] = i; 8 break; 9 } 10 } 11 if(res[0] == -1){ 12 return res; 13 } 14 for(int j = len - 1; j >= 0; j--){ 15 if(nums[j] == target){ 16 res[1] = j; 17 break; 18 } 19 } 20 return res; 21 } 22 }
本来想直接暴力从左到右 但是要考虑目标元素个数为一时 end数组越界的问题
大佬的思路直接从左到右扫描 左一次记录位置一右一次记录位置二
如果第一次没有发现的话直接跳出 时间复杂度的话O(N)还算好理解
但题目要求是O(logN) 所以继续想方法二咯
1 public int[] searchRange(int[] nums, int target) { 2 int start = 0; 3 int end = nums.length - 1; 4 int[] ans = { -1, -1 }; 5 if (nums.length == 0) { 6 return ans; 7 } 8 while (start <= end) { 9 int mid = (start + end) / 2; 10 if (target == nums[mid]) { 11 //这一步保证了退出的时候start一定在目标第一次出现的位置 12 end = mid - 1; 13 } else if (target < nums[mid]) { 14 end = mid - 1; 15 } else { 16 start = mid + 1; 17 } 18 } 19 //考虑 tartget 是否存在,判断我们要找的值是否等于 target 并且是否越界 20 if (start == nums.length || nums[ start ] != target) { 21 return ans; 22 } else { 23 ans[0] = start; 24 } 25 ans[0] = start; 26 start = 0; 27 end = nums.length - 1; 28 while (start <= end) { 29 int mid = (start + end) / 2; 30 if (target == nums[mid]) { 31 //这一步保证了退出的时候end一定在目标第二次出现的位置 32 start = mid + 1; 33 } else if (target < nums[mid]) { 34 end = mid - 1; 35 } else { 36 start = mid + 1; 37 } 38 } 39 ans[1] = end; 40 return ans; 41 }
思路其实很好懂 两次二分查找 因为退出的条件不同
第一次是end<start 第二次是start > end
所以可以分别推算出start和end的值(和思路一也有点像 汗Orzzzzz
算法的时间复杂度:算法的T(n) =O(logn),则称其具有对数时间
常见的具有对数时间的算法有二叉树的相关操作和二分搜索。
其实确定二分查找的退出点也是二分查找的难点之一 明天有空整理一下

浙公网安备 33010602011771号