layout: posttitle: PHP 求解在排序数组中查找元素的第一个和最后一个位置
subtitle: PHP 求解在排序数组中查找元素的第一个和最后一个位置
date: 2020-12-02
author: he xiaodong
header-img: img/default-post-bg.jpg
catalog: true
tags:
- Go
- PHP
- LeetCode 34
- 排序数组
- 二分查找
- 位置

在排序数组中查找元素的第一个和最后一个位置

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

进阶:

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

示例 1:

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

示例 2:

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

示例 3:

  1. 输入:nums = [], target = 0
  2. 输出:[-1,-1]

提示:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路 1

暴力查找加处理特殊结果

  1. class Solution {
  2. /**
  3. * @param Integer[] $nums
  4. * @param Integer $target
  5. * @return Integer[]
  6. */
  7. function searchRange($nums, $target) {
  8. // 设置默认值
  9. $result = [-1, -1];
  10. if (empty($nums)) {
  11. return $result;
  12. }
  13. // 循环 + 暴力赋值 $result
  14. $i = 0;
  15. foreach ($nums as $key => $num) {
  16. if ($num == $target) {
  17. if ($i == 0) {
  18. $result[0] = $key;
  19. } else {
  20. $result[1] = $key;
  21. }
  22. $i++;
  23. }
  24. }
  25. // 兼容只出现一次的情况
  26. if ($result[0] !== -1 && $result[1] == -1) {
  27. return [$result[0], $result[0]];
  28. }
  29. return $result;
  30. }
  31. }

解题思路 2

利用二分法思路,先利用二分法找到符合 target 的值,再分别用二分法求 target 起始的位置和结束的位置。

  1. class Solution {
  2. /**
  3. * @param Integer[] $nums
  4. * @param Integer $target
  5. * @return Integer[]
  6. */
  7. function searchRange($nums, $target) {
  8. $result = [-1, -1];
  9. if (empty($nums)) {
  10. return $result;
  11. }
  12. $left = 0;
  13. $count = count($nums);
  14. $right = $count - 1;
  15. while ($left <= $right) {
  16. $mid = round($left + ($right - $left) / 2);
  17. if ($nums[$mid] == $target) {
  18. $left = $mid;
  19. $right = $mid;
  20. // 如果 $nums[$left - 1] == $nums[$left],则继续二分法找起始位置
  21. while ($left > 0 && $nums[$left - 1] === $nums[$left]) {
  22. --$left;
  23. }
  24. // 如果 $nums[$right + 1] == $nums[$right],则继续二分法找结束位置
  25. while ($right < $count - 1 && $nums[$right] === $nums[$right + 1]) {
  26. ++$right;
  27. }
  28. $result[0] = $left;
  29. $result[1] = $right;
  30. break;
  31. } else if ($nums[$mid] > $target) {
  32. $right = $mid - 1;
  33. } else {
  34. $left = $mid + 1;
  35. }
  36. }
  37. return $result;
  38. }
  39. }

参考链接:

  1. 极客时间 算法面试通关40讲

最后恰饭 阿里云全系列产品/短信包特惠购买 中小企业上云最佳选择 阿里云内部优惠券