题目描述

原题链接

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。

进阶:

  • 你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?

示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

示例 3:
输入:nums = [], target = 0
输出:[-1,-1]

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一个非递减数组
  • -109 <= target <= 109

个人解法

Javascript

  1. /*
  2. * @lc app=leetcode.cn id=34 lang=javascript
  3. *
  4. * [34] 在排序数组中查找元素的第一个和最后一个位置
  5. */
  6. // @lc code=start
  7. /**
  8. * @param {number[]} nums
  9. * @param {number} target
  10. * @return {number[]}
  11. */
  12. var searchRange = function (nums, target) {
  13. if (!nums || !nums.length) return [-1, -1];
  14. let left = -1;
  15. let leftFlag = false;
  16. let right = nums.length;
  17. let rightFlag = false;
  18. while (left < right) {
  19. if (!leftFlag && nums[++left] === target) {
  20. leftFlag = true;;
  21. }
  22. if (!rightFlag && nums[--right] === target) {
  23. rightFlag = true;
  24. }
  25. if (leftFlag && rightFlag) {
  26. break;
  27. }
  28. }
  29. return [leftFlag ? left : -1, rightFlag ? right : -1];
  30. };

Java(二分查找)

  1. class Solution {
  2. public int[] searchRange(int[] nums, int target) {
  3. int n1, n2;
  4. int[] result = new int[2];
  5. if(nums.length==0){
  6. int[] r = new int[]{-1,-1};
  7. return r;
  8. }
  9. n1=search(nums, target);
  10. if (nums[n1]!=target){
  11. n1=-1;
  12. }
  13. n2=search(nums, target+1);
  14. if(n1!=-1&&nums[n2]>target){
  15. n2-=1;
  16. }else if(n1==-1){
  17. n2=-1;
  18. }
  19. result[0]=n1;
  20. result[1]=n2;
  21. return result;
  22. }
  23. public int search(int[] nums, int target){
  24. int left = 0, len = nums.length, right = len - 1, mid;
  25. while (left < right) {
  26. //5778810 0 0
  27. mid = (left + right) / 2;
  28. if (target <= nums[mid]) {
  29. right=mid;
  30. } else {
  31. left = mid + 1;
  32. }
  33. }
  34. return left;
  35. }
  36. }

其他解法

Java

Javascript

二分查早是最优的

改进的二分法

  1. //nums = [5,7,7,8,8,10], target = 8
  2. const binarySearch = (nums, target, lower) => {
  3. let left = 0, right = nums.length - 1, ans = nums.length;
  4. while (left <= right) {
  5. const mid = Math.floor((left + right) / 2);
  6. if (nums[mid] > target || (lower && nums[mid] >= target)) {
  7. right = mid - 1;
  8. ans = mid;
  9. } else {
  10. left = mid + 1;
  11. }
  12. }
  13. return ans;
  14. }
  15. var searchRange = function(nums, target) {
  16. let ans = [-1, -1];
  17. const leftIdx = binarySearch(nums, target, true);
  18. const rightIdx = binarySearch(nums, target, false) - 1;
  19. if (leftIdx <= rightIdx && rightIdx < nums.length && nums[leftIdx] === target && nums[rightIdx] === target) {
  20. ans = [leftIdx, rightIdx];
  21. }
  22. return ans;
  23. };