二分法

二分法的时间复杂度是O(logn),所以在算法中,比O(n)更优的时间复杂度几乎只能是O(logn)的二分法。

根据时间复杂渡来倒推算法也是面试中的常用策略:题目中若要求算法的时间复杂度是O(logn),那么这个算法基本上就是二分法。

在这里,我们不做二分法的基本概念介绍,直接给出实现二分最基本的代码。具体理由看注释。

在这里特别说明:

在二分法中的while循环只是用于缩小查找范围,直至缩小到我们能够直接可辩别的范围内。而最后结果的return是依靠最后的if语句来比较并实现的。

  1 class solution{
  2 
  3     public:
  4         int binarySearch(int nums[], int target)
  5         {
  6             //判断传入的数组不为空
  7             if(nums == NULL || sizeof(nums) / sizeof(int) == 0)
  8             {
  9                 return -1;
 10             }
 11             
 12             int len = sizeof(nums) / sizeof(int);
 13             int start  = 0;
 14             int end = len - 1;
 15             
 16             
 17         //这里判断条件是start + 1< end
 18         //终止时是start + 1 = end;
 19         //这样终止时是start和end是相邻的两个下标。
 20         
 21         //注意:我们并没有在while语句里面直接得到并return
 22         //while只是缩小了区间范围
 23         //而是把范围缩小到了我们易于操作的两个索引的范围内,
 24         //并且通过后面的if语句来判断并return
 25         while(start + 1 < end)
 26         {
 27             //这里没有采用middli = (start + end) / 2;
 28             //原因是避免当start和end很大的时候形成溢出
 29             int middle = start + (start - end) / 2;
 30             
 31             if(nums[midddle] == target)
 32             {
 33                 middle = end;
 34             }
 35             else if(nums[middle] < target)
 36             {
 37                 start = middle + 1;
 38             }
 39             
 40             else
 41             {
 42                 end = middle - 1;
 43             }
 44             
 45         }
 46         
 47         if(nums[start] == target)
 48         {
 49             return start;
 50         }
 51         if(nums[end] == target)
 52         {
 53             return end;
 54         }
 55         else
 56         {
 57             return -1;
 58         }
 59             
 60             
 61         }
 62         
 63         int binarySearch_v2(int nums[], int target)
 64         {
 65             if(nums == NULL || sizeof(nums) / sizeof(int) == 0)
 66             {
 67                 return -1;
 68             }
 69             
 70             int len  = sizeof(nums) / sizeof(int);
 71             int start = 0;
 72             int end = len - 1;
 73             
 74             //这里判断语句是start < end;
 75             //跳出循环时start = end
 76             //所以在后面的if语句判断中只有nums[start] == target
 77             
 78             //因为int middle = start + (start - end) / 2具有向左靠拢的性质
 79             //所以这里的更新条件为start = middle + 1, end = middle - 1
 80             while(start < end)
 81             {
 82                 int middle = start + (start - end) / 2;
 83                 
 84                 if(nums[middle] == target)
 85                 {
 86                     start = middle;
 87                 }
 88                 else if(nums[middle] < target)
 89                 {
 90                     start = middle + 1;
 91                 }
 92                 else:
 93                 {
 94                     end = middle - 1;
 95                 }
 96             }
 97             
 98             if(nums[start] = target)
 99             {
100                 return start;
101             }
102             else:
103             {
104                 return -1;
105             }
106             
107             
108         }        
109 }

二,二分位置之OOXX

在这种题目中,可以将OO视为不满足某个条件,而将XX视为满足某个条件,这样就可以把一个数组或者序列分为OO....OOXX....XX类型。而这样的题目往往是给出一个数组,要求找出数组中第一个/最后一个满足条件的位置。

  OOOOO....OOOXXX...XXXXX

对于这样的题目可以采用二分法进行。

三:在一个经过排序的数组元素超级多的数组中找出目标元素。

解决这样的问题,方式一:暴力求解,直接按顺序去除数组中元素与目标值target进行比较,这样的算法的时间复杂度是O(n),当然,在生活中也是不愿意看到的。方式二:二分法求解。

我们先来说明c++中vector的实现原理,然后将这样的原理移植到我们的二分算法中。

 

 三:找出经过旋转后的排序数组中的最小值

例题:假设一个排好序的数组在其某一未知点发生了旋转(比如0 1 2 4 5 6 7 可能变成4 5 6 7 0 1 2)。你需要找到其中最小的元素。

所谓旋转后的排序数组,首先这个数组是经过排序的,数组中所有的元素都是按照一定的顺序排列(递增或者递减),其次是这个数组经过了旋转,使得这个数组的排列性质出现了阶段性。如图:

对于这样的数组,要想找出数组中的最小值,可以直接采用暴力求解,使用for循环进行遍历,但是这样的算法的时间复杂度是O(n),并且如果采用这样的算法也没什么技术性可言。除了暴力求解,那么就是对这个旋转后的数组进行二分查找。其时间复杂度是O(logn),其思路如下图

 

 

 还有一种类型是根据判断,保留有解的那一半而去掉无解的那一部分。

 

 

 

 

 

 

原文地址:https://www.cnblogs.com/hxhlrq/p/13387538.html