LeetCode33—搜索旋转排序数组

方法一:先找到旋转点,然后根据目标值重新确定二分查找区域。

时间复杂度:用到两次二分查找,每次二分查找粗略的认为是O(logn),那么时间复杂度为2 * O(logn);

空间复杂度:O(1)。

 1 int search(vector<int>& nums, int target) {
 2         if (!nums.size())    return -1;
 3         
 4         int low = 0, high = nums.size() - 1, mid;
 5         int rotate = 0;    //旋转点
 6         //第一步先找到旋转点
 7         if (nums[low] <= nums[high])    rotate = 0;    //无旋转
 8         else
 9         {
10              while (low < high)
11              {
12                  mid = low + ((high - low) >> 1);
13                  if (nums[mid] > nums[mid + 1])    break;
14                  
15                  if (nums[mid] >= nums[low])    low = mid;
16                  else    high = mid;
17              }
18             rotate = mid + 1;
19         }
20         //重新规划二分查找区域
21         if (!rotate)    
22         {
23             low = 0;
24             high = nums.size() - 1;
25         }
26         else 
27         {
28             if (nums[0] == target)    return 0;
29             else if (nums[0] > target)
30             {
31                 low = rotate;
32                 high = nums.size() - 1;
33             }
34             else
35             {
36                 low = 0;
37                 high = rotate - 1;
38             }   
39         }
40         //二分查找
41         while (low <= high)
42         {
43             mid = low + ((high - low) >> 2);
44             if (nums[mid] == target)    return mid;
45             else if (nums[mid] > target)    high = mid - 1;
46             else    low = mid + 1;
47         }
48         
49         return -1;
50     }

 

方法二:根据中间点和其他条件来调整上下边界。其实一开始就想的这个办法,但是写的过程中发现很混乱,所以就写了上一种比较清晰的方法。这个方法的关键是确定哪半边是有序的,在这个前提下分情况讨论会很清晰。

时间复杂度:O(logn),空间复杂度:O(1)。

 1 int search(vector<int>& nums, int target) {
 2         if (!nums.size())    return -1;    //数组为空
 3         
 4         int low = 0, high = nums.size() - 1, mid;
 5         if (nums[low] <= nums[high])    //数组无旋转点,即升序排列
 6         {
 7             while (low <= high)
 8             {
 9                 mid = low + ((high - low) >> 1);
10                 if (nums[mid] == target)    return mid;
11                 else if (nums[mid] > target) high = mid - 1;
12                 else low = mid + 1;
13             }
14             return -1;
15         }
16         else    //数组有旋转点
17         {
18             while (low <= high)
19             {
20                 mid = low + ((high - low) >> 1);
21                 if (nums[mid] == target)    return mid;
22                 
23                 if (nums[mid] > nums[low])    //左半边有序
24                 {
25                     if (nums[low] < target && nums[mid] > target)    high = mid - 1;
26                     else if (nums[low] == target)    return low;
27                     else    low = mid + 1;
28                 }
29                 else    //右半边有序
30                 {
31                     if (nums[high] > target && nums[mid] < target)    low = mid + 1;
32                     else if (nums[high] == target)    return high;
33                     else    high = mid - 1;
34                 }
35             }
36             return -1;
37         }
38     }

 

总结:1)分析时把握问题的特征,不要没有头绪的想,不然就是猜了;

           2)O(logn)复杂度是非常优秀的时间复杂度。

posted @ 2019-04-18 09:28  zpchya  阅读(154)  评论(0编辑  收藏  举报