博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
34. Search for a Range
阅读量:7122 次
发布时间:2019-06-28

本文共 3402 字,大约阅读时间需要 11 分钟。

Given an array of integers sorted in ascending order, 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].

分析


思路1:

首先想到的思路是用二分法查找到target,然后从target开始,同时向左右两边扩展窗口,但是最坏的时间复杂度是O(n);

思路2:

采用递归,recursive。
终止条件:
1. 当 nums[l] == target == nums[r]
    返回{l,r}
2. 当 target 落在 [nums[l],nums[r]]之外,返回{-1,-1}
递归部分:
当 nums[l] <= target <= nums[r],
分别对左半边和后半边进行search。同时将两个结果进行合并。
假设有一数组nums[],我们把它分为两部分
A...B  C...D
当出现终止条件中的一条时,都会立即返回;
如果俩个部分都进入了递归部分,说明 
A <= target <= B
C <= target <= D
所以可以得知,
target = B = C 
那么A..B的左边界就是nums的左边界,C..D的右边界就是nums的右边界,否则返回其中一个不是{-1,-1}的结果,就是这样合并两个结果的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class 
Solution {
public
:
    
vector<
int
> searchRange(vector<
int
>& nums, 
int 
target) {
        
return 
helper(nums, 0, nums.size() - 1, target);
    
}
    
vector<
int
> helper(vector<
int
> & nums,
int 
l, 
int 
r, 
int 
target){
        
if
(nums.empty())
return 
vector<
int
>{-1,-1};
        
if
(nums[l] == target && target == nums[r]){
            
return 
vector<
int
>{l,r};
        
}
        
else 
if
(nums[l] <= target && target <= nums[r]){
            
int 
mid = (l + r) >> 1;
            
vector<
int
> L = helper(nums, l, mid, target);
            
vector<
int
> R = helper(nums, mid+1, r, target);
            
if
(L[0] != -1 && R[0] != -1){
                
return 
vector<
int
> {L[0],R[1]};
            
}
            
else 
if
(L[0] != -1){
                
return 
L;
            
}
            
else
{
// 剩下的 R 不为{-1, -1} 和 R 是{-1, -1}的情况可以合并
                
return 
R;
            
}
        
}
        
return 
vector<
int
>{-1, -1};
    
}
};

思路3:

使用一般的二分查找,找到target的首个元素
然后再找 target+1 可以插入的首个位置,
这两者之间即为所求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class 
Solution {
public
:
    
vector<
int
> searchRange(vector<
int
>& nums, 
int 
target) {
        
if
(nums.empty()) 
return 
vector<
int
> {-1, -1};
        
int 
l = bs(nums, target);
        
if
(nums[l] == target){
            
int 
r = bs(nums, target + 1);
            
/**
             
* 当nums的最后一个元素是target的时候,需要将边界r自增才是可以插入target+1的位置
             
* 比如[2,2,2]则r的值是2,和[2,2,4]的返回值同是2,
             
*/
             
            
if
(nums[r] == target) 
                
r++;
            
return 
vector<
int
> {l, r - 1};
        
}
        
else
{
            
return 
vector<
int
> {-1, -1};
        
}
    
}
    
// using binary search to find the first element in nums or the position that could be used to insert the element
    
int 
bs(vector<
int
> & nums, 
int 
target){
        
int 
l = 0, r = nums.size() - 1, mid;
        
while
(l < r){
            
mid = (l + r) >> 1;
            
if
(nums[mid] < target){
                
l = mid + 1;
            
}
            
else
{
                
r = mid;
            
}
        
}
        
return 
r;
    
}
};

思路4

写两个找边界的函数,一个找上边界,一个找下边界;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class 
Solution {
public
:
    
vector<
int
> searchRange(vector<
int
>& nums, 
int 
target) {
        
if
(nums.empty()) 
return 
vector<
int
> {-1, -1};
        
int 
l = lob(nums, target);
        
if
(nums[l] == target){
            
int 
r = upb(nums, target);
            
return 
vector<
int
> {l, r};
        
}
        
return 
vector<
int
> {-1, -1};
    
}
     
    
int 
lob(vector<
int
> & nums, 
int 
target){
        
int 
l = 0, r = nums.size() - 1, mid;
        
while
(l < r){
            
mid = (l + r) >> 1; 
// insure the mid always be at the lower position
            
if
(nums[mid] < target){
                
l = mid + 1;
            
}
            
else
{
                
r = mid;
            
}
        
}
        
return 
r;
    
}
     
    
int 
upb(vector<
int
> & nums, 
int 
target){
        
int 
l = 0, r = nums.size() - 1, mid;
        
while
(l < r){
            
mid = (l + r + 1) >> 1;
// insure the mid always be at the upper position
            
if
(nums[mid] > target){
                
r = mid - 1;
            
}
            
else
{
                
l = mid;
            
}
        
}
        
return 
l;
    
}
};

转载于:https://www.cnblogs.com/zhxshseu/p/c8ae187c169beb07f9646be57ee2ec22.html

你可能感兴趣的文章
global2.min.css 公用样式2.0版本
查看>>
探索React生态圈
查看>>
远程唤醒
查看>>
关于怎么查出数据库的值一系列的方法
查看>>
web前端研发工程师编程能力成长之路 [转]
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
Linux 系统参数修改命令sysctl
查看>>
Exchange 2013 OAB不能下载的解决办法
查看>>
hibernate之关于使用连接表实现多对一关联映射
查看>>
PXE+Kickstart无人值守安装
查看>>
笑傲大数据时代,你必须要知道的41个Scala实战技能!
查看>>
radio单选框回显时,不能使用readonly属性,为使它不可编辑
查看>>
linux下mysql修改密码及关闭远程连接
查看>>
Hadoop之HDFS之一致性模型
查看>>
eclipse常用设置
查看>>
Web性能优化方向
查看>>
U盘安装win7准备
查看>>
支付宝和微信横扫境外商户,外国人冷眼旁观
查看>>
RedHat 7配置KVM和桥接
查看>>