旋转数组的查找,删除以及转折点

什么是旋转数组?

Suppose a sorted array 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).

有一个转折点,0 ,需要考虑的特殊情况是 [1,2], [2,1]

进阶形式是这个数组中有重复的元素   尤其要注意 [1,1],   [3,1,3],   [4,4,4,4,4,4,1,2,3,4,4],    [4,1,2,3,4,4,4,4,4,4,4]  这几种情况


第一类问题,在旋转数组中查找目标数 (无重复的元素)

思想:先求中间点的值A[mid]
①,如果A[mid] >= A[left], 说明从left到mid 是升序的,然后再判断target在不在这个区间,如果在,则让右边界right=mid-1,如果不在,则让左边界left=mid+1;

②,如果A[mid] < A[left],说明从mid到right都是升序,则同样道理判断target区间

代码如下:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    int search(int A[], int n, int target) {
        int left  = 0;
        int right = n-1;
        int mid ;

        while(left<=right){
            mid = (left+right)/2;
            if(target == A[mid])
                return mid;
            if(A[mid]>=A[left]) //说明从left到mid是升序的,等号必须有,因为考虑输入为[3,1];
            {
                if((target>=A[left]) && (target<=A[mid]))
                    right = mid-1;
                else
                    left  = mid+1;
            }

            else //说明从mid到right是升序的;
            {
                if(target>=A[mid] && target<=A[right])
                    left = mid+1;
                else
                    right = mid-1;
            }
        }
        return -1;
 }
};




int main()
{
    int result;
    Solution solution1;
    int ia[3]={2,3,1};
    //vector<int> vec(ia, ia+9);
    int target;
    cout<<"please input the target: ";
    cin >>target;
    result = solution1.search(ia, 3, target );
    cout << "the result_index is " << result <<endl;
}

如果有重复元素,该怎么办?

干扰的因素是  A[left]==A[mid]==A[right]这种情况, 对于这种情况,去掉首尾继续下一次循环,代码如下:

class Solution {
public:
    bool search(int A[], int n, int target) {
        if(0 == n) return false;
        int left  = 0;
        int right = n-1;
        int mid ;

        while(left<=right){
            mid = (left+right)/2;
            if(target == A[mid])
                return true;
            if(A[left] == A[mid] && A[mid] == A[right])
            {
               ++left;
               --right;
            }
            else if(A[mid]>=A[left]) //说明从left到mid升序或者相等的;
            {
                if((target>=A[left]) && (target<A[mid]))
                    right = mid-1;
                else
                    left  = mid+1;
            }

            else //说明从mid到right是升序或者相等的;
            {
                if(target>A[mid] && target<=A[right])
                    left = mid+1;
                else
                    right = mid-1;
            }
        }
        return false;
 }
};


第二类问题:求转折点,也就是最小点 (无重复)

思路:

1,num[left] < num[right] 本身就是递增,直接返回num[left], num[left] == num[right] 也是循环结束的条件 返回num[left]

2,num[mid] >= num[left]  说明从left到mid是递增的,让left=mid+1,必须是大于等于,考虑输入[2,1]

3,num[mid] < num[left]  说明从mid到right是递增的,让right = mid 缩小范围  

具体代码如下:

class Solution {
public:
    int findMin(vector<int> &num) {
        int left = 0;
        int right = num.size() - 1;
        int mid;
        while(left <= right){
            mid = (left + right) / 2;
            if(num[left] <= num[right]) return num[left];
            else if(num[mid] >= num[left]) left = mid + 1;
            else right = mid;
        }
    }
};


对于有重复元素的情况:

class Solution {
public:
    int findMin(vector<int> &num) {
        int left = 0;
        int right = num.size() - 1;
        int mid;
        while(num[left] >= num[right]){//这里必须是大于等于,考虑[3,1,3]情况出现,直接返回3
            if(left >= right) return num[left];//这里必须是大于等于,考虑[1,1]情况出现
            mid = (left + right)/2;
            if(num[mid]==num[left] && num[mid]==num[right]){++left; --right;} //[4,5,6,7,1,2,3,4,4,4,4,4,4,4,4]以及[4,4,4,4,4,1,2,3,4]情况
            else if(num[mid] >= num[left]) left = mid+1;
            else  right = mid;
        }
        return num[left];
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值