leetcode Ch1-search 2014
class Solution {
public:
int searchInsert(int A[], int n, int target) {
int left=,right=n-;
while(left<=right)
{
int mid=left+(right-left)/;
if(A[mid]==target) return mid;
if(A[mid]<target)
left=mid+;
else right=mid-;
}
return left;
}
};
当循环结束时,如果没有找到目标元素,那么left一定停在恰好比目标大的元素的index上,right一定停在恰好比目标小的index上.
特殊点的例子:当在{1,2,3,4,5}里执行二分查找找0时,此时的left=0, right=-1.(left和right也是挺拼的,为了比target大/小,不惜越界。)
这个规律非常有用,合理利用left和right在未找到target的情况下退出while循环时的特性,能解决很多问题,尤其体现在实现upperBound和lowerBound函数时。如果要利用left或right,需要保证target不在当前区间内,这样才能让while循环以未找到target的状态退出。为了实现这一点,我们需要在即使发现target==A[mid]的情况下仍然假装没看见,继续缩小搜索范围。
因此如果要在二分搜索的基础上计算bound的话,其实就是怎么处理那几个值为target的元素的问题。也就是是否把这部分值恰好为target的元素纳入下一轮搜索范围。(二分搜索本质上就是不断缩小搜索范围)。
以upperBound为例。upperBound函数是找[left,right]内第一个大于target的元素下标------所以值为target的元素肯定要排除在搜索范围之外。这样当A[mid]==target时我们仍将其排除在搜索范围外,即让low=mid+1。一直到搜索范围里已经没有值为target的元素了,此时根据二分查找的性质,当区间里没有找到target时,while循环退出后low指向刚好大于target的位置,high指向刚好小于target的位置。所以此时我们返回low即为刚好大于target的位置,即——第一个大于target的位置。
lowerBound同理。lowerBound是寻找[left,right]内第一个值不小于target的元素下标。“不小于”target的不好求,但刚好小于target的那个元素位置比较好求,因为这就是right的返回值。所以我们按照上述思路,在遇到A[mid]==target的情况下仍假装看不见,继续缩小搜索范围,直到当前范围里没有了target,最终循环退出时right就指向值刚好小于target的元素位置。而(right+1)即为不小于target的元素下标。
lowerBound和upperBound的实现代码在下一题代码中。
What if there are duplicates?
class Solution {
public:
vector<int> searchRange(int A[], int n, int target) {
int left=,right=n-;
vector<int> res(,-);//[-1,-1]是默认值
while(left<=right)
{
int mid=left+(right-left)/;
if(A[mid]<target)
left=mid+;
else if(A[mid]>target)
right=mid-;
else
{
res[]=lowerBound(A,left,mid,target);
res[]=upperBound(A,mid,right,target)-;//别忘了减1
return res;
}
}
return res;//这一句别忘了。当查找失败时返回[-1,-1].
}
private:
int upperBound(int A[], int left, int right, int target)
{
int low = left, high = right;
while (low <= high)
{
int mid = low + (high - low) / ;
if (A[mid] <= target)
low = mid + ;
else
high = mid - ;
}
return low;
}
int lowerBound(int A[], int left, int right, int target)
{
int low = left, high = right;
while (low <= high)
{
int mid = low + (high - low) / ;
if (A[mid] >= target)
high = mid - ;
else
low = mid + ;
}
return high + ;
}
};
lowerBound和upperBound与binarySearch之间的关系上一题里已经分析过了。
注意几个小细节,已在注释中标明。细节决定成败,bug-free需要谨小慎微。
3. Search in Rotated Sorted Array
class Solution {
public:
int search(int A[], int n, int target) {
int left=,right=n-;
while(left<=right)
{
int mid=left+(right-left)/;
if(A[mid]==target) return mid;
if(A[mid]<A[right])//说明右半段是有序的
{
if(target>A[mid]&&target<=A[right])
left=mid+;
else
right=mid-;
}
else
{
if(target>=A[left]&&target<A[mid])
right=mid-;
else
left=mid+;
}
}
return -;
}
};
最关键的把握这个规律:"总有一半是有序的,而且和另一半无区间重叠"。code ganker的总结很好。
4. Search in Rotated Sorted Array II
class Solution {
public:
bool search(int A[], int n, int target) {
for(int i=;i<n;i++)
if(A[i]==target) return true;
return false;
}
};
由于允许有duplicates,会导致没有办法像I中那样根据A[mid]和A[left]、A[right]的比较来确定是哪一半有序,应该在哪一半查找。
导致最坏时间复杂度变为O(n)。因此用最简单的遍历来实现就可以。
class Solution {
public:
bool searchMatrix(vector<vector<int> > &matrix, int target) {
if(matrix.size()==||matrix[].size()==) return false;
int m=matrix.size(); int n=matrix[].size();
int left=,right=m*n-;
while(left<=right)
{
int mid=left+(right-left)/;
int midX=mid/n; int midY=mid%n;//注意:这里是n,不是m!
if(matrix[midX][midY]==target) return true;
if(matrix[midX][midY]<target)
left=mid+;
else
right=mid-;
}
return false;
}
};
6. sqrt(x)
class Solution {
public:
int sqrt(int x) {
if(x<) return x;
int left=,right=x/+;
while(left<=right)
{
int mid=left+(right-left)/;
if(mid<=x/mid&&(mid+)>x/(mid+))//防止溢出
return mid;
if(mid>x/(mid))
right=mid-;
else
left=mid+;
}
return -;
}
};
比较蹊跷的是if(mid>x/mid)和下面的else不能换位置。尚不知为何。
leetcode Ch1-search 2014的更多相关文章
- [LeetCode] 034. Search for a Range (Medium) (C++/Java)
索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 035. Sea ...
- [LeetCode] 033. Search in Rotated Sorted Array (Hard) (C++)
指数:[LeetCode] Leetcode 解决问题的指数 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 033. ...
- [array] leetcode - 35. Search Insert Position - Easy
leetcode - 35. Search Insert Position - Easy descrition Given a sorted array and a target value, ret ...
- [array] leetcode - 34. Search for a Range - Medium
leetcode - 34. Search for a Range - Medium descrition Given an array of integers sorted in ascending ...
- [array] leetcode - 33. Search in Rotated Sorted Array - Medium
leetcode - 33. Search in Rotated Sorted Array - Medium descrition Suppose an array sorted in ascendi ...
- LeetCode 81 Search in Rotated Sorted Array II [binary search] <c++>
LeetCode 81 Search in Rotated Sorted Array II [binary search] <c++> 给出排序好的一维有重复元素的数组,随机取一个位置断开 ...
- LeetCode 33 Search in Rotated Sorted Array [binary search] <c++>
LeetCode 33 Search in Rotated Sorted Array [binary search] <c++> 给出排序好的一维无重复元素的数组,随机取一个位置断开,把前 ...
- [LeetCode] Binary Search 二分搜索法
Given a sorted (in ascending order) integer array nums of n elements and a target value, write a fun ...
- [leetcode]81. Search in Rotated Sorted Array II旋转过有序数组里找目标值II(有重)
This is a follow up problem to Search in Rotated Sorted Array, where nums may contain duplicates. 思路 ...
- Java for LeetCode 081 Search in Rotated Sorted Array II
Follow up for "Search in Rotated Sorted Array": What if duplicates are allowed? Would this ...
随机推荐
- 'node' 不是内部或外部命令,也不是可运行的程序或批处理文件
状况:安装完nodejs之后,命令行输入node -v, 提示 'node' 不是内部或外部命令,也不是可运行的程序或批处理文件原因:检查环境变量没有配置正确配置环境变量: windows系统里, 需 ...
- oracle12c之四 控制PDB操作 PDBLockdown Profiles
除了IO.内存.CPU之外,还有一些限制,比如:限制在pdb中的操作命令,我们可以创建一个lockdown profile来限制对当前PDB的操作,增强某些操作的安全性. 关于PDB Lockdo ...
- Testlink 机器重启后Access denied for user 'admin '@'localhost' (using password: YES)解决
问题表现: 装完Testlink,重启系统后,在testlink权限未分配会出现如下提示: 1045 - Access denied for user 'Testlink '@'localhost' ...
- kafka集群安装及简单使用
关于kafka是什么及原理,请参考kafka官方文档的介绍:http://kafka.apache.org/documentation/#introduction ,英文不好的同学可以看这里http: ...
- Js正则Replace方法
JS正则的创建有两种方式: new RegExp() 和 直接字面量. //使用RegExp对象创建 var regObj = new RegExp("(^\s+)|(\s+$)" ...
- dfs.replication、dfs.replication.min/max及dfs.safemode.threshold.pct
一.参数含义 dfs.replication:设置数据块应该被复制的份数: dfs.replication.min:所规定的数据块副本的最小份数: dfs.replication.max:所规定的数据 ...
- oracle系统包——DBMS_PIPE用法
DBMS_PIPE包用于在同一例程(实例)的不同会话之间进行通信:注意,如果用户要执行包dbms_pipe中的过程和函数,则必须要为用户授权. sql>conn sys/oracle as sy ...
- 游戏开发者注意!这个音频SDK可以完美兼容所有主流游戏引擎
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯游戏云 发表于云+社区专栏 在网络游戏中,无论是大逃杀.棋牌类.电子竞技类还是娱乐休闲类小游戏,玩家和玩家之间的互动.语音聊天是一 ...
- iostat命令——监控系统设备的IO负载情况
iostat命令的安装 #yum install sysstat iostat常见选项 -t 输出数据时打印搜集数据的时间 -m 输出的数据以MB为单位 -d 显示磁盘的统计信息 # iost ...
- awk常用命令总结
awk工具,主要将一行分成“字段”来处理. awk '条件类型1{动作1} 条件类型2{动作2}...‘ filename awk主要是处理每一行的字段内的数据,而默认的字段的分隔符为空格键或[tab ...