剑指offer&&leetcode 二分系列

1: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., [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.

Your algorithm’s runtime complexity must be in the order of O(log n).

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1

题目意思:就是用O(n)的时间复杂度在一个旋转了的有序数组中找到target值。

解析:这个题目我觉得挺难得。

首先看[0,1,2,4,5,6,7]的变形
[7,0,1,2,4,5,6]
[6,7,0,1,2,4,5]
[5,6,7,0,1,2,4]
[4,5,6,7,0,1,2]
[2,4,5,6,7,0,1]
[1,2,4,5,6,7,0]

这里写图片描述

class Solution {
public:
    int search(vector<int>& nums, int target)
    {
        if(nums.size()==0) return -1;
        int l = 0;
        int r = nums.size()-1;
        while(l<=r)
        {
            int mid = (l+r)>>1;
            if(nums[mid]==target) return mid;
            else if(nums[mid]<nums[r])
            {
                if(nums[mid]<target&&nums[r]>=target) l = mid+1;
                else r = mid-1;
            }
            else
            {
                if(target>=nums[l]&&nums[mid]>target) r = mid-1;
                else l = mid+1;
            }
        }
        return -1;
    }
};

2:旋转数组的最小数字

题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

这个最简单的方法当然是从头到尾进行遍历,时间复杂度为O(n),但是效率比较低。

另外一种方法就是二分,首先数组进行旋转以后,前后分成了两个有序的序列,例如 3,4,5,1,2,那么我们可以利用二分

首先将left = 0right = size-1,
那么算出mid的值,如果array[mid]>=array[left],那么说明还处于前面那个有序数组中,这时候可以将left = mid,但是如果array[mid]<array[right],那么说明处于后面那个有序数组中,可以将right = mid,最后结束的条件是 left只想前面有序数组的最后一个元素,而right只想第二个有序数组的第一个元素。即left = right-1。但是也有特殊情况:
1:如果数组没有旋转,即为原样,即1,2,3,45.则最开始array[left]>=array[right]不成立,那么直接返回array[0]即可。
2:如果array[left],array[mid],array[right],所指的值都一样,那么必须从头到尾遍历。举例,
1,110,1array[left] = 1,array[mid] = 1,array[4] = 1,不知道到底哪个是处于有序的序列中,这时候只能遍历整个数组才行。

代码:

class Solution 
{
public:
    int in_order(vector<int>rotateArray)
    {
        int min_value = rotateArray[0];
        int len = rotateArray.size();
        for(int i=1;i<len;i++)
        {
            if(rotateArray[i]<min_value)  min_value = rotateArray[i];
        }
        return min_value;
    }

    int minNumberInRotateArray(vector<int>rotateArray)
    {
        if(rotateArray.size()==0)  return 0;
        int size = rotateArray.size();
        int l = 0 ,r = size-1;
        int mid = 0;
        while(rotateArray[l]>=rotateArray[r])
        {
            if(r-l==1)
            {
                mid = r;
                break;
            }
            int mid = (l+r)>>1;
            if(rotateArray[l]==rotateArray[mid]&&rotateArray[r]==rotateArray[mid])  return in_order(rotateArray);
            if(rotateArray[mid]>=rotateArray[l]) l = mid;
            else r = mid;
        }
        return rotateArray[mid];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值