1. Search Insert Position

  1. class Solution {
  2. public:
  3. int searchInsert(int A[], int n, int target) {
  4. int left=,right=n-;
  5. while(left<=right)
  6. {
  7. int mid=left+(right-left)/;
  8. if(A[mid]==target) return mid;
  9. if(A[mid]<target)
  10. left=mid+;
  11. else right=mid-;
  12. }
  13. return left;
  14. }
  15. };

当循环结束时,如果没有找到目标元素,那么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?

2. Search for a Range

  1. class Solution {
  2. public:
  3. vector<int> searchRange(int A[], int n, int target) {
  4. int left=,right=n-;
  5. vector<int> res(,-);//[-1,-1]是默认值
  6. while(left<=right)
  7. {
  8. int mid=left+(right-left)/;
  9. if(A[mid]<target)
  10. left=mid+;
  11. else if(A[mid]>target)
  12. right=mid-;
  13. else
  14. {
  15. res[]=lowerBound(A,left,mid,target);
  16. res[]=upperBound(A,mid,right,target)-;//别忘了减1
  17. return res;
  18. }
  19. }
  20. return res;//这一句别忘了。当查找失败时返回[-1,-1].
  21. }
  22. private:
  23. int upperBound(int A[], int left, int right, int target)
  24. {
  25. int low = left, high = right;
  26. while (low <= high)
  27. {
  28. int mid = low + (high - low) / ;
  29. if (A[mid] <= target)
  30. low = mid + ;
  31. else
  32. high = mid - ;
  33. }
  34. return low;
  35. }
  36. int lowerBound(int A[], int left, int right, int target)
  37. {
  38. int low = left, high = right;
  39. while (low <= high)
  40. {
  41. int mid = low + (high - low) / ;
  42. if (A[mid] >= target)
  43. high = mid - ;
  44. else
  45. low = mid + ;
  46. }
  47. return high + ;
  48. }
  49. };

lowerBound和upperBound与binarySearch之间的关系上一题里已经分析过了。

注意几个小细节,已在注释中标明。细节决定成败,bug-free需要谨小慎微。

3. Search in Rotated Sorted Array

  1. class Solution {
  2. public:
  3. int search(int A[], int n, int target) {
  4. int left=,right=n-;
  5. while(left<=right)
  6. {
  7. int mid=left+(right-left)/;
  8. if(A[mid]==target) return mid;
  9. if(A[mid]<A[right])//说明右半段是有序的
  10. {
  11. if(target>A[mid]&&target<=A[right])
  12. left=mid+;
  13. else
  14. right=mid-;
  15. }
  16. else
  17. {
  18. if(target>=A[left]&&target<A[mid])
  19. right=mid-;
  20. else
  21. left=mid+;
  22. }
  23. }
  24. return -;
  25. }
  26. };

最关键的把握这个规律:"总有一半是有序的,而且和另一半无区间重叠"。code ganker的总结很好。

4. Search in Rotated Sorted Array II

  1. class Solution {
  2. public:
  3. bool search(int A[], int n, int target) {
  4. for(int i=;i<n;i++)
  5. if(A[i]==target) return true;
  6. return false;
  7. }
  8. };

由于允许有duplicates,会导致没有办法像I中那样根据A[mid]和A[left]、A[right]的比较来确定是哪一半有序,应该在哪一半查找。

导致最坏时间复杂度变为O(n)。因此用最简单的遍历来实现就可以。

5. Search a 2D Matrix

  1. class Solution {
  2. public:
  3. bool searchMatrix(vector<vector<int> > &matrix, int target) {
  4. if(matrix.size()==||matrix[].size()==) return false;
  5. int m=matrix.size(); int n=matrix[].size();
  6. int left=,right=m*n-;
  7. while(left<=right)
  8. {
  9. int mid=left+(right-left)/;
  10. int midX=mid/n; int midY=mid%n;//注意:这里是n,不是m!
  11. if(matrix[midX][midY]==target) return true;
  12. if(matrix[midX][midY]<target)
  13. left=mid+;
  14. else
  15. right=mid-;
  16. }
  17. return false;
  18. }
  19. };

6. sqrt(x)

  1. class Solution {
  2. public:
  3. int sqrt(int x) {
  4. if(x<) return x;
  5. int left=,right=x/+;
  6. while(left<=right)
  7. {
  8. int mid=left+(right-left)/;
  9. if(mid<=x/mid&&(mid+)>x/(mid+))//防止溢出
  10. return mid;
  11. if(mid>x/(mid))
  12. right=mid-;
  13. else
  14. left=mid+;
  15. }
  16. return -;
  17. }
  18. };

比较蹊跷的是if(mid>x/mid)和下面的else不能换位置。尚不知为何。

leetcode Ch1-search 2014的更多相关文章

  1. [LeetCode] 034. Search for a Range (Medium) (C++/Java)

    索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 035. Sea ...

  2. [LeetCode] 033. Search in Rotated Sorted Array (Hard) (C++)

    指数:[LeetCode] Leetcode 解决问题的指数 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 033. ...

  3. [array] leetcode - 35. Search Insert Position - Easy

    leetcode - 35. Search Insert Position - Easy descrition Given a sorted array and a target value, ret ...

  4. [array] leetcode - 34. Search for a Range - Medium

    leetcode - 34. Search for a Range - Medium descrition Given an array of integers sorted in ascending ...

  5. [array] leetcode - 33. Search in Rotated Sorted Array - Medium

    leetcode - 33. Search in Rotated Sorted Array - Medium descrition Suppose an array sorted in ascendi ...

  6. LeetCode 81 Search in Rotated Sorted Array II [binary search] <c++>

    LeetCode 81 Search in Rotated Sorted Array II [binary search] <c++> 给出排序好的一维有重复元素的数组,随机取一个位置断开 ...

  7. LeetCode 33 Search in Rotated Sorted Array [binary search] <c++>

    LeetCode 33 Search in Rotated Sorted Array [binary search] <c++> 给出排序好的一维无重复元素的数组,随机取一个位置断开,把前 ...

  8. [LeetCode] Binary Search 二分搜索法

    Given a sorted (in ascending order) integer array nums of n elements and a target value, write a fun ...

  9. [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. 思路 ...

  10. 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 ...

随机推荐

  1. JavaWeb——Servlet如何调用线程池中的线程?

    tomcat线程池与servlet https://blog.csdn.net/qq_27817797/article/details/54025173 https://blog.csdn.net/l ...

  2. MySQL比较运算符的子查询

    使用比较运算符的子查询 =.>.<.>=.<=.<>.!=.<=> 语法结构 operand comparison_operator subquery ...

  3. Robot Framework自动化测试一(第一个脚本)

    创建测试项目                                           选择菜单栏file----->new Project Name 输入项目名称,Type 选择Di ...

  4. 在unity中使用protobuf

    https://www.jianshu.com/p/b135676dbe8d 上面的提供序列化和常见的序列化有点不一样 下面的是常见的序列化的,但是他没有讲怎么用工具生成.proto--->.c ...

  5. nexus开机启动

    在/etc/init.d目录下创建nexus文件 #!/bin/bash #chkconfig: #description:nexus3 #processname:nexus3 export JAVA ...

  6. 【c++】iostreeam中的类为何不可以直接定义一个无参对象呢

    缘起 #include <iostream> #include <fstream> #include <sstream> using namespace std; ...

  7. pyquery库简介

    html = '''<div><ul><li class="item-0">li0</li><li class="i ...

  8. wtl学习总结

    在windows平台,相比MFC,我更喜欢WTL,因其简洁漂亮.所以陆续花了一年的时间学习之,这里总结一下(在学习Wtl/Atl之前,最好是对WinApi编程有一定的了解). 安装 Wtl主页 htt ...

  9. js扩展

    http://www.css88.com/doc/underscore/#findWhere

  10. linux压缩和解压缩命令大全[转]

    .tar 解包:tar zxvf FileName.tar 打包:tar czvf FileName.tar DirName ------------------------------------- ...