【问题标题】:How to get the pivot point in a sorted rotated array with duplicate elements iteratively?如何迭代地获取具有重复元素的排序旋转数组中的枢轴点?
【发布时间】:2019-08-14 07:27:09
【问题描述】:

使用循环在具有重复项的旋转排序数组中查找枢轴点。尽管我在建议中找到了解决方案,但那是使用递归。我需要一个使用递归的解决方案。从过去的 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。

【问题讨论】:

  • 题外话:你不修改向量,所以引用应该是const。
  • 你能解释一下这是怎么跑题的吗?
  • 正确的 const-ness 并不能解决您所遇到的真正问题,所以...
  • 你能帮我解释一下程序的逻辑吗?
  • 还有答案吗?

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


【解决方案1】:

问题来了:

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

您不能安全地使用此条件,将其修改为使用&gt;= 或与nums[lo]&lt;&lt;= 结合使用也无济于事;考虑以下两个序列:

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

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

因此,如果您最终处于这种情况(nums[x] 与所有lohimid 相同),则必须检查两半!我想两个递归调用最容易实现。请注意,如果三个索引处的任何值不同,则不需要递归; 如果你需要递归,只有两个子结果中的一个,真正的后继者会更小,所以这个就是最终结果。

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

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);

由于数组已排序,最后一个条件只能对idxLoidxHigh 中的任何一个为真;如果所有元素都相等,我选择的测试将导致选择向量的第一个元素(nums[idxLo] &gt; nums[(idxLo + 1] ? /*...*/; 将选择最后一个)。

辅助函数将提供公共接口:

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

借助 lambda,您可以完全隐藏工作函数。不幸的是,不直接支持递归 lambda,因此您需要依赖 this answer 中所示的一个小技巧:

int findPivot(std::vector const& nums)
{
    size_t n = nums.size();
    auto findPivotRecursively = [&nums, &n] (int hi, int lo, auto& fpr) -> int
    {
        // ...
        else
        {
            int idxLo = fpr(hi, lo, fpr);
            // ...
        }
        // ...
    };
    return findPivotRecursively(0, nums.size() - 1, findPivotRecursively);
}

【讨论】:

  • 请您解释一下我到底需要添加或更改什么?
  • "递归到下半部和上半部!"我该怎么做?
  • 每个递归算法都可以变成迭代算法。问题在于,如果需要递归,则需要在某处存储下半部分和上半部分的边界。根据算法,这可能会有点棘手;为了比较,here 是快速排序的迭代变体;你可以做类似的事情;不过,您的变体会有点复杂,因为您需要在对两半进行排序后做进一步的事情......
猜你喜欢
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多