[array] leetcode - 33. Search in Rotated Sorted Array - Medium
leetcode - 33. Search in Rotated Sorted Array - Medium
descrition
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.
解析
两种方法的时间复杂度和空间复杂度都是一样的,不过思考的思路有所不同,不过根本都是对二分查找的改进。方法 1 对应代码 int searchDirectly(vector& nums, int target); 方法 2 对应 int searchAssist(vector& nums, int target)。虽然 方法 2 对应的代码量要大一些,但思路还是值得借鉴的,这里也一并给出。
注意点:
- 当 target 找不到的时候返回 -1
- 可以假设数组中的元素都是唯一的 (这是代码优化的关键!)
一般的:
直接在原数组上进行二分查找。对于数组 arry[0,...,n-1] 可以将其分成两个部分 left_part = arry[0,...,imax], right_part=arry[imax+1, ..., n-1],其中 imax 指向数组中最大的元素,那么 left_part 和 right_part 都是递增的,并且 left_part 中所有的值都大于 right_part 中的值。
对于 binary search,假设 [ileft, ... , irigt] 确定 arry 中的一个子数组。下面就讨论,我们如何在每次查找中将查找空间减少一半的思路。
每次而分查找我们需要计算 imid = (ileft + iright) / 2,即中间元素的位置,将数组均分成两半。这时我们可以根据 imid 的位置来确定下一次的查找范围。
- condition1: 如果 arry[ileft] < arry[imid] : 说明 imid 在 left_part 的 ascending 子数组中
- condition2: 如果 arry[imid] < arry[irigh] : 说明 imid 在 rigt_part 的 ascending 子数组中
注意:因为 left_part < right_part ,因此以上两种情况是对立的。如果 ileft, imid, iright 指向的 3 个数相等,我们将无法判断 imid 处在数组的那个部分,也就无法达到划分的目的,这是题意的关键优化点。
方法 1
- 如果 condition1 成立,那么 [ileft, ..., imid] 是递增有序的
- 如果 target 在 [ileft, ..., imid] 区间内,则 ileft = imid-1
- 否则 ileft = imid + 1
- 如果 condition2 成立,那么 [imid, ..., iright] 是递增有序的
- 如果 target 在 [imid, ..., iright] 区间内,则 ileft = imid + 1
- 否则 iright = imid - 1
每一次查找都能使搜索空间减半。具体实现看代码,注意细节和边界条件。
方法 2
- 我们可以先找到数组中最小值的位置 imin,那么相对于原来递增有序的数,新的 rotated 数组中元素的位置 i' = (i + imin)%n。比如 4 5 6 7 0 1 2, imin = 4,相当于原数组 0 1 2 4 5 6 7 循环右移了 imin 步。找最小值的位置也是使用折半查找的思想,时间复杂度 O(log(n))。
- 针对原数组 0 1 2 4 5 6 7 使用而分查找,每次而分查找比较时,使用 i' = (i + imin)%n 计算真是的 middle 位置。这样可以达到减办的效果。时间复杂度 O(log(n)) 。
具体实现查看代码。虽然这样的方法比钱前一种方法来说代码量大,实际上做了两次而分查找,但这里新地址的映射方式是个很好的思考思路。
code
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Solution{
public:
int search(vector<int>& nums, int target){
// You may assume no duplicate exists in the array.
//return searchDirectly(nums, target);
return searchAssist(nums, target);
}
// time-O(log(n)), space-O(1)
int searchDirectly(vector<int>& nums, int target){
int ileft = 0;
int iright = nums.size()-1;
while(ileft <= iright){
int imid = (ileft+iright)/2;
if(nums[imid] == target){
return imid;
}
// nums[imid] != target
if(nums[ileft] <= nums[imid]){
// nums[ileft,...,imid] is ascending
// Note: don't forget to check nums[ileft] == target
if(nums[ileft] <= target && target < nums[imid]){
iright = imid - 1;
}else{
ileft = imid + 1;
}
}else{
// nums[imid] < nums[iright]
// nums[imid,...,iright] is ascending
// Note: don't forget to check target == nums[iright]
if(nums[imid] < target && target <= nums[iright]){
ileft = imid + 1;
}else{
iright = imid - 1;
}
}
}
return -1;
}
// time-O(log(n)), space-O(1)
int searchAssist(vector<int>& nums, int target){
if(nums.empty())
return -1;
// the number of rotated of each element in nums
int irotated = findMinInRotatedArray(nums);
int n = nums.size();
int ileft = 0;
int iright = nums.size() - 1;
while(ileft <= iright){
int imid = (ileft + iright) / 2;
int imidReal = (imid + irotated) % n; // calculate the real index of middle value
if(nums[imidReal] == target){
return imidReal;
}else if (nums[imidReal] < target){
ileft = imid + 1;
}else{
// nums[imidReal] > target
iright = imid - 1;
}
}
return -1;
}
int findMinInRotatedArray(vector<int>& nums){
if(nums.empty())
return -1;
if(nums[0] < nums[nums.size()-1]) // nums in ascending
return 0;
// binary search
int ileft = 0;
int iright = nums.size() - 1;
while(ileft+1 < iright){
int imid = (ileft + iright) / 2;
if(nums[ileft] < nums[imid]){
ileft = imid;
}else{
// nums[imid] < nums[iright]
iright = imid;
}
}
// ileft point to the maximum
// iright point to the minimum
return iright;
}
};
int main()
{
return 0;
}
[array] leetcode - 33. Search in Rotated Sorted Array - Medium的更多相关文章
- LeetCode 33 Search in Rotated Sorted Array [binary search] <c++>
LeetCode 33 Search in Rotated Sorted Array [binary search] <c++> 给出排序好的一维无重复元素的数组,随机取一个位置断开,把前 ...
- [LeetCode] 33. Search in Rotated Sorted Array 在旋转有序数组中搜索
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...
- LeetCode 33. Search in Rotated Sorted Array(在旋转有序序列中搜索)
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...
- leetCode 33.Search in Rotated Sorted Array(排序旋转数组的查找) 解题思路和方法
Search in Rotated Sorted Array Suppose a sorted array is rotated at some pivot unknown to you before ...
- LeetCode 33.Search in Rotated Sorted Array(M)
题目: Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. ( ...
- leetcode 33. Search in Rotated Sorted Array
Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...
- Java [leetcode 33]Search in Rotated Sorted Array
题目描述: Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 ...
- [leetcode]33. Search in Rotated Sorted Array旋转过有序数组里找目标值
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...
- LeetCode 33 Search in Rotated Sorted Array(循环有序数组中进行查找操作)
题目链接 :https://leetcode.com/problems/search-in-rotated-sorted-array/?tab=Description Problem :当前的数组 ...
随机推荐
- Python 简单理解多线程
进程,是一个或多个线程的集合,每个进程在内存中是相对独立的. 线程,是计算机最小的运算单元,每个进程至少要有一个线程,多个线程时,每个线程间之间共享内存. 分别举例常规运行和多线程运行: 0)常规运行 ...
- 流式处理的新贵 Kafka Stream - Kafka设计解析(七)
原创文章,转载请务必将下面这段话置于文章开头处. 本文转发自技术世界,原文链接 http://www.jasongj.com/kafka/kafka_stream/ Kafka Stream背景 Ka ...
- BST 解析 (一)
这篇博文主要初步介绍Binary Search Tree(BST)的一些基本功能以及应用场景,由于BST的相关知识比较多,下一节会接着补充BST的一些功能.这一节主要分为以下三个要素: BST 的定义 ...
- 一个web图片热点生成工具(winform开发) 附源码
给图片加热点是web开发中经常用到的一个功能.这方面的工具也不少. 为了更好的满足自己的需求,写了一个winform程序. 可以方便的给图片加热点,更方便灵活! 源码下载 http://downloa ...
- Dubbo源码学习--服务发布(ProxyFactory、Invoker)
上文分析了Dubbo服务发布的整体流程,但服务代理生成的具体细节介绍得还不是很详细.下面将会接着上文继续分析.上文介绍了服务代理生成的切入点,如下: Invoker<?> invoker ...
- WinForm下的loading框实现
前言:在项目使用C/S模式情况下,由于需要经常进行数据的刷新,如果直接进行刷新,会有一个等待控件重画的过程,非常的不友好,因此在这里添加一个loading框进行等待显示. 实现:在经过多方面查询资料, ...
- Selenium中如何使用xpath更快定位
在学习Selenium路上,踩了也不少坑,这是我最近才发现的一个新写法,好吧,"才发现"又说明我做其他事了.对的,我现在还在加班! 开车~~~ 例子:知乎网 标签:Python3. ...
- Codeforces 869E The Untended Antiquity
题意:给定一个网格图,三种操作:1.在(r1,c1,r2,c2)处建围墙.2.删除(r1,c1,r2,c2)处的围墙.3.询问两点是否可达 思路比较巧妙,将围墙内的点赋加一个权值,询问的时候判断两个点 ...
- Nginx的反向代理与负载均衡
1.1 集群是什么 简单地说,集群就是指一组(若干个)相互独立的计算机,利用高速通信网络组成的一个较大的计算机服务系统,每个集群节点(即集群中的每台计算机)都是运行各自服务的独立服器.这些服务器之间可 ...
- Android开发之漫漫长途 Ⅷ——Android Binder(也许是最容易理解的)
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...