如何迭代获取具有重复元素的排序旋转数组中的枢轴点?

时间:2019-03-23 13:46:28

标签: c++ arrays algorithm vector binary-search

使用循环在具有重复项的旋转排序数组中查找枢轴点。尽管我在建议中找到了解决方案,但这是使用递归的。我需要使用递归的解决方案。从最近的12小时开始,我就一直困扰着这个问题。任何帮助将不胜感激。

直到现在,我一直尝试找到单元格,该单元格周围的两个元素都大于元素本身。但是它似乎没有用。谁能告诉我我要去哪里错了。

int findPivot(vector<int>& nums)
{
    int lo=0,hi=nums.size()-1,mid,n=nums.size();
    while(lo<=hi)
    {
        mid = (lo+hi)>>1;
        if(nums[(mid+1)%n] >= nums[mid] && nums[(mid-1+n)%n]>nums[mid])
            return mid;
        if(nums[mid]>nums[hi])
            lo = mid+1;
        else
            hi = mid-1;
    }
    return 0;
}

但是对于这样的情况,[3,1]似乎不起作用,我得到0,预期输出为1和[1,1,3,1] 3我得到0。

1 个答案:

答案 0 :(得分:0)

问题在这里:

if(nums[mid] > nums[hi])

您不能安全地使用此条件,将其修改为使用>=或与nums[lo]组合使用,将其更改为<<=都无济于事;考虑以下两个序列:

{ 1, 1, 1, 2, 1 }
{ 1, 2, 1, 1, 1 }
  0     2     4
 lo    mid    hi 

使用lohi any 组合与上述任何一个比较器,由于选择了不良的一半,两个序列之一将被错误地评估!您在序列{ 1, 1, 3, 1 }中遇到了这种情况。

因此,如果您遇到这种情况(nums[x]lohi都相等),则必须检查一半!我认为最容易实现两个递归调用。请注意,如果三个索引中的任何值不同,则无需递归。 如果您需要递归,则仅对于两个子结果之一,实际后继项会较小,因此该结果将是最终结果。

您可以检测到e。 G。如下:

mid

假设您已将该功能转换为带有签名的递归功能

if(nums[mid] > nums[hi] || nums[mid > nums[lo])
{
    hi = mid - 1;
}
else if(nums[mid] < nums[lo] || nums[mid] < nums[high]
{
    lo = mid + 1;
}
else
{
    int idxLo = findPivotRecursively(nums, lo, mid - 1);
    int idxHi = findPivotRecursively(nums, mid + 1, high);
    return nums[idxHi] > nums[(idxHi + 1) % n] ? idxHi : idxLo;
}

对数组进行排序时,最后一个条件仅对int findPivotRecursively(std::vector const& nums, int high, int low); idxLo中的一个为真;如果所有元素都相等({idxHigh将选择最后一个),那么我选择的测试将导致选择向量的第一个元素。

助手功能将提供公共接口:

nums[idxLo] > nums[(idxLo + 1] ? /*...*/;

借助lambda,您可以完全隐藏工作功能。不幸的是,递归lambda不受直接支持,因此您将依靠this answer中所示的小技巧:

int findPivot(std::vector const& nums)
{
    return findPivotRecursively(nums, 0, nums.size() - 1);
}