C++二进制搜索来查找不动点的索引

C++ Binary Search to find the index of fixed point

本文关键字:索引 查找 二进制 搜索 C++      更新时间:2023-10-16

我正在实现一个函数,该函数找到a[I]=I的不动点。

size_t find_fixed_point(const vector<int>& list)
{
    auto lower = list.begin();
    auto upper = list.end() - 1;
    while (lower < upper)
    {
        auto mid = lower + (upper-lower)/2;
        if ( *mid <= (mid - list.begin()) )
        {
            // keep searching on left side
            upper = mid;
        }
        else
        {
            // keep searching on right side
            lower = mid + 1;
        }
    }
    return lower - list.begin();
}

所以如果我把这个应用到下面的向量

    vector<int> numbers = {-10, -5, 1, 3, 13, 13, 50, 70};

auto temp = find_fixed_point(numbers);
cout << numbers[temp];

它应该给出3作为固定点,但仅仅给我-10是行不通的。

这个算法看起来不错,但不起作用。有人有主意吗?谢谢,

我认为您的比较运算符的方法不对:

size_t find_fixed_point(const vector<int>& list)
{
    auto lower = list.begin();
    auto upper = list.end() - 1;
    while (lower < upper)
    {
        auto mid = lower + (upper-lower)/2;
        if ( *mid >= (mid - list.begin()) )
        {
            // keep searching on left side
            upper = mid;
        }
        else
        {
            // keep searching on right side
            lower = mid + 1;
        }
    }
    return lower - list.begin();
}

一个可能的解决方案是使用标准库算法,在本例中为std::find_if():

int index = 0;
auto result = std::find_if( std::begin( v ) , std::end( v ) , [&]( int value ) { return value == index++; } );

但这里的问题是std::find_if()O(n),使用简单的线性遍历。

因此,如果您想要O(logn)解决方案,如您的问题中所述,请使用二进制搜索解决方案。我同意ilent2的回答,问题是"交换"比较:应该是>=,而不是<=

#include<iostream>
#include<vector>
using namespace std;
size_t find_fixed_point(const vector<int>& list)
{
    auto lower = list.begin();
    auto upper = list.end() - 1;
    while (lower < upper)
    {   
        auto mid = lower + (upper-lower)/2;
        if ( *mid > (mid - list.begin()) )
        {   
            // keep searching on left side
            upper = mid;
        }   
        else if ( *mid < (mid - list.begin()) )
        {   
            // keep searching on right side
            lower = mid + 1;
        }   
        else 
            return mid - list.begin();  
    }   
     return lower - list.begin();
}
int main()
{
    vector<int> numbers = {-10, -5, 1, 3, 13, 13, 50, 70};  
    auto temp = find_fixed_point(numbers);
    cout << numbers[temp];
}