博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【LeetCode & 剑指offer刷题】查找与排序题6:33. Search in Rotated Sorted Array(系列)
阅读量:4959 次
发布时间:2019-06-12

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

33. Search in Rotated Sorted Array

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e.,
 
[0,1,2,4,5,6,7]
 
might become
 
[4,5,6,7,0,1,2]
).
You are given a target value to search. If found in the array return its index, otherwise return
 
-1
.
You may assume no duplicate exists in the array.
Your algorithm's runtime complexity must be in the order of 
O
(log 
n
).
Example 1:
Input: nums = [4,5,6,7,0,1,2], target = 0
Output:
4
Example 2:
Input:
nums = [
4,5,6,7,0,1,2]
, target = 3
Output:
-1
 
 
/* 
掌握
问题:在旋转数组中查找(不存在重复数字)
方法:二分查找,先找有序范围,再判断有序范围内有没有,更新
left
right
指针,不断缩小范围
 
O(logn)
*/
class
Solution
{
public
:
   
int
search
(
vector
<
int
>&
a
,
int
target
)
   
{
       
if
(
a
.
empty
())
return
-
1
;
       
       
int
left
=
0
,
right
=
a
.
size
()
-
1
;
       
while
(
left
<=
right
)
       
{
           
int
mid
=
(
left
+
right
)
/
2
;
           
           
if
(
a
[
mid
]
==
target
)
               
return
mid
;
           
else
if
(
a
[
mid
]
<
a
[
right
])
//
若中间数小于最右边的数,则右半段(
mid~right
)是有序的
           
{
               
if
(
target
>
a
[
mid
]
&&
target
<=
a
[
right
])
//
在有序的半段里用首尾两个数来判断目标值是否在这一区域内
                    left
=
mid
+
1
;
//
说明在
mid~right
内,更新
left
位置
               
else
                    right
=
mid
-
1
;
           
}
           
else
                       
//
若中间数大于最右边的数,则左半段
(left~mid)
是有序的
           
{
               
if
(
target
>=
a
[
left
]
&&
target
<
a
[
mid
])
//
由于判断下来不可能有
target = a[mid]
,故这里没有取等号
                    right
=
mid
-
1
;
//
说明在
left~mid
内,更新
right
位置
               
else
                    left
=
mid
+
1
;
           
}
       
}
       
return
-
1
;
   
}
};
 
//此方法技巧性较高,了解即可
//方法:二分查找(因为有O(logn)的限制)
class
Solution
{
public
:
   
int
search
(
vector
<
int
>&
a
,
int
target
)
   
{
       
if
(
a
.
empty
())
return
-
1
;
//特殊情况:空数组
       
       
//使用二分查找找到最小值的索引(旋转的地方)
       
//旋转之后左半边数组比右半边数组大,通过二分查找,找到分界点(最小值)即可,最小值在左半数组最末尾,右半数组起始位置
       
int
n
=
a
.
size
();
       
int
left
=
0
,
right
=
n
-
1
;
       
int
indexmin
=
0
;
//初始化最小值的位置
       
while
(
a
[
left
]
>
a
[
right
])
//特殊情况:输入有序数组,可以看成rotate 0,则直接退出循环,indexmin用初始值0
       
{
           
int
mid
=
(
left
+
right
)/
2
;
           
if
(
a
[
mid
]>
a
[
right
])
left
=
mid
;
//a[mid]>a[right]说明mid在左半边数组,将left指针移至mid
           
else
right
=
mid
;
//a[mid]<a[right]说明mid在右半边数组,将right指针移至mid
           
if
(
right
-
left
==
1
)
           
{
                indexmin
=
right
;
break
;
//跳出循环
           
}
       
}
//循环结束后left指向左半数组末尾,right指向右半数组开头
       
//找序列中的极小值(联系find peak element这题)
        left
=
0
;
right
=
n
-
1
;
       
//使用常规的二分查找(对于增序序列而言),并考虑旋转
       
while
(
left
<=
right
)
       
{
           
int
mid
=
(
left
+
right
)/
2
;
           
int
realmid
=
(
mid
+
indexmin
)%
n
;
//indexmin为数组中最小数的位置(本来为0位置,现在变为rot位置),相当于附加偏移以找到真正的mid位置
           
if
(
a
[
realmid
]
<
target
)
left
=
mid
+
1
;
           
else
if
(
a
[
realmid
]
>
target
)
right
=
mid
-
1
;
           
else
return
realmid
;
       
}
       
return
-
1
;
//未找到
    
   
}
};
 
 
81
.
 
Search in Rotated Sorted Array II
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e.,
 
[0,0,1,2,2,5,6]
 
might become
 
[2,5,6,0,0,1,2]
).
You are given a target value to search. If found in the array return
 
true
, otherwise return
 
false
.
Example 1:
Input:
nums = [2
,5,6,0,0,1,2]
, target = 0
Output:
true
Example 2:
Input:
nums = [2
,5,6,0,0,1,2]
, target = 3
Output:
false
Follow up:
  • This is a follow up problem to 
    , where 
    nums
     may contain duplicates.
  • Would this affect the run-time complexity? How and why?

 
/*
问题:在旋转数组中查找
2
(可以存在重复数字)
方法:二分查找,先找有序范围,再判断有序范围内有没有,更新
left
right
指针,不断缩小范围
如果
a[mid]
a[right]
相等,则让
right--
直到不相等,其余部分与问题
Search in Rotated Sorted Array I
相同
O(logn)
*/
class
Solution
{
public
:
   
bool
search
(
vector
<
int
>&
a
,
int
target
)
   
{
       
if
(
a
.
empty
())
return
false
;
       
       
int
left
=
0
,
right
=
a
.
size
()
-
1
;
       
while
(
left
<=
right
)
       
{
           
int
mid
=
(
left
+
right
)
/
2
;
           
           
if
(
a
[
mid
]
==
target
)
               
return
true
;
           
else
if
(
a
[
mid
]
<
a
[
right
])
//
若中间数小于最右边的数,则右半段(
mid~right
)是有序的
           
{
               
if
(
target
>
a
[
mid
]
&&
target
<=
a
[
right
])
//
在有序的半段里用首尾两个数来判断目标值是否在这一区域内
                    left
=
mid
+
1
;
//
说明在
mid~right
内,更新
left
位置
               
else
                    right
=
mid
-
1
;
           
}
           
else
if
(
a
[
mid
]
>
a
[
right
])
//
若中间数大于最右边的数,则左半段
(left~mid)
是有序的
           
{
               
if
(
target
>=
a
[
left
]
&&
target
<
a
[
mid
])
//
由于判断下来不可能有
target = a[mid]
,故这里没有取等号
                    right
=
mid
-
1
;
//
说明在
left~mid
内,更新
right
位置
               
else                   
                    left
=
mid
+
1
;
           
}
           
else             //若中间数等于最右边数,移动right指针
                right
--;
       
}
       
return
false
;
   
}
};
 
 
 
 

 

转载于:https://www.cnblogs.com/wikiwen/p/10225932.html

你可能感兴趣的文章
【Manthan, Codefest 18 (rated, Div. 1 + Div. 2) C】Equalize
查看>>
【codeforces 767A】Snacktower
查看>>
【MemSQL Start[c]UP 3.0 - Round 1 C】 Pie Rules
查看>>
Ognl中“%”、“#”、“$”详解
查看>>
我对应用软件——美团的看法
查看>>
我最喜欢的 5 个 Gedit 插件
查看>>
OOoLatex:在 OpenOffice.org 中拔出 Latex 公式
查看>>
linu学习第二天:文件系统相关操作
查看>>
执行了的程序,才是你的程序.
查看>>
在AxureRP8中实现广告文字滚动效果
查看>>
jQuery获取CSS样式中的颜色值的问题
查看>>
struts2.x + Tiles2.x读取多个xml 配置文件
查看>>
Sqlite文件在ubunut的查看
查看>>
表单校验之datatype
查看>>
python第六篇文件处理类型
查看>>
kettle 数据库连接失败
查看>>
ListView失去焦点选中行不能高亮显示的问题解决
查看>>
# jsp及servlet学习笔记
查看>>
Kconfig详解
查看>>
(四)hadoop系列之__hadoop搭建(单机配置)
查看>>