Algorithm 非排序数组中的局部极小值

Algorithm 非排序数组中的局部极小值,algorithm,Algorithm,假设我有一个数组a[I]表示0,我假设这是一个家庭作业问题,所以我回答得很恰当。如果您正在搜索局部最小值,则必须为您提供起始位置,因为您需要“局部”的引用。如果左侧的元素小于该元素,请转到该元素并重试。否则,如果右侧的元素小于当前值,请向右移动并重试。否则,当前元素是本地最小值 编辑:在我阅读问题后,添加了O(logn)时间要求。我会考虑一个满足这一要求的解决方案 另一个编辑:我认为对于未排序的数组,在O(logn)的时间要求中,这是不可能的,因为没有办法将问题一分为二。另一方面,对于排序数组有

假设我有一个数组a[I]表示0,我假设这是一个家庭作业问题,所以我回答得很恰当。如果您正在搜索局部最小值,则必须为您提供起始位置,因为您需要“局部”的引用。如果左侧的元素小于该元素,请转到该元素并重试。否则,如果右侧的元素小于当前值,请向右移动并重试。否则,当前元素是本地最小值

编辑:在我阅读问题后,添加了O(logn)时间要求。我会考虑一个满足这一要求的解决方案


另一个编辑:我认为对于未排序的数组,在O(logn)的时间要求中,这是不可能的,因为没有办法将问题一分为二。另一方面,对于排序数组有一个简单的O(1)解决方案:)

除非数组有其他约束,否则在没有(至少)线性时间预处理的情况下,您无法在O(logn)中找到局部最小值,因为在最坏的情况下,您需要检查数组中的每个元素。形式上证明这一说法并不困难,其想法是构造这样的阵列,对于每种扫描方法,该方法将在线性时间内对构造的阵列起作用

例如,想象一下,如果你从开始到结束都在做一个大小为
n
的数组的简单扫描:如果你的最小值在
n-1
-th位置,那么你只有在
n-1
迭代后才能发现它,也就是
O(n)


>B/>P> < P>首先,我们需要考虑局部最小值是如何定义的:

a[i] < a[i-1] and a[i] < a[i+1]
我认为这应该是足够的灵感,让你完成的方法


请注意,扩展此方法仅适用于唯一值,例如一个全1的数组,除非您执行一些边缘情况检测,否则它不会有O(logn)运行时间。

此方法与O(logn)中的二进制搜索方法类似,但仅适用于数组中有一个局部最小值和不同数字的情况。您的阵列必须如下所示:

8 5 4 3 [1] 2 6 9
一个是本地最小值

检查边界。 如果a[0]a[n],则a[n]是局部最小值。 如果这些条件都不正确-开始分割:


检查a[n/2],如果a[n/2]>a[n/2+1],则在数组右侧显示局部最小值,否则在左侧显示局部最小值。然后递归地解决问题。

编辑:只有当局部最小值由“定义时,这才有效。我无法反驳此解决方案的有效性,因此,如果有人可以,我会很高兴

考虑从1到n索引的数组“a”

low = 1
high = n
mid = (low + high)/2
在不损失太多通用性的情况下,我将假设数组值是不同的。 因此,在mid,a[mid-1],a[mid],a[mid+1]可以是:

Case 1:

/\


Case 2:

\/

Case 3:

 / 
/

Case 4:

 \
  \

Case 5(boundary):
/

Case 6(boundary):
\
&m=中等

可使用以下if条件检查每种情况:

1: a[m] > a[m-1] && a[m] > a[m+1]
2: a[m] < a[m-1] && a[m] < a[m+1]
3: a[m] > a[m-1] && a[m] < a[m+1]
4: a[m] < a[m-1] && a[m] > a[m+1]
1:a[m]>a[m-1]&a[m]>a[m+1]
2:a[m]a[m-1]&a[m]a[m+1]
我也将忽略对边界情况的解释:

第二种情况是期望的情况,其中a[m]是局部极小值

对于第三种情况:

在左边总是有一个局部极小值,因此,设置h=m-1并继续

第四种情况:

右边总是有一个局部极小值,所以,l=m+1,然后继续

对于第一种情况,我可以选择任意方向: 我相信这是有效的,因为你唯一一次减少你正在考虑的部分是当你确定在减少的部分有一个局部极小值,所以你搜索的部分将总是有一些局部极小值


注意:这只适用于查找单个局部极小值,而不是每个局部极小值。后一种情况需要O(n),因为您肯定必须至少查看整个数组一次。

通过使用一种二进制搜索,可以在
O(logn)
中解决此问题

该技巧在中得到了很好的解释。该网站提供了递归实现

我实际上提出了另一个迭代实现,如下所示

#include <cstdio>
#include <vector>
using std::vector;

int SearchLocalMinima(const vector<int>& sspace) {
        if (sspace.size() < 2)
                return -1;
        if (sspace.size() == 2)
                return 0;
        int L = 0, U = sspace.size() - 1;
        while (L<U) {
                int M = L + (U - L) / 2;
                if (M - 1 == L) {
                        if (sspace[M] <= sspace[M + 1])
                                return M;
                        else
                                return M + 1;
                } else {
                        if (sspace[M] <= sspace[M + 1])
                                U = M + 1;
                        else
                                L = M;
                }

        }
        return -1;
}

int main() {
        vector<int> values{64, 14, 52, 27, 71, 19, 63, 1, 16, 57};
        printf("Local minima: %d\n", SearchLocalMinima(values));
        return 0;
}
#包括
#包括
使用std::vector;
int SearchLocalMinima(常量向量和空间){
if(sspace.size()<2)
返回-1;
if(sspace.size()=2)
返回0;
int L=0,U=sspace.size()-1;

while(LSo,有什么原因不能在if语句中循环使用那个小提示吗?@GioBorje为什么不添加一个答案?记住,数组没有排序。@GioBorje,重读标题。@DennisMeng-那不是O(n),不是O(logn)?它至少改变了问题三次。三次!投票结束了该问题。被认为是“本地”的定义在问题中//不是我投了反对票;-)@kirilloid我知道是的,但是可能有很多局部极小值,你需要一个参考点来确定你要找的是哪一个。实际上,OP可能在找类似en.wikipedia.org/wiki/Trialum_search的东西。如果一个数组只有一个局部极小值,或者它被排序(升序或降序无关),你可以在O(logn)中找到局部最优。如果我们将数组重新排序为“6 8[1]5 9 4 3 2 6”。我们取n/2,它是9,它>4,所以我们在右边递归,但局部最小值在左边。问题只是要求我们找到一个局部最小值,在你的例子中,算法应该给出
“6 8 1 5 9 4 3[2]6”
#include <cstdio>
#include <vector>
using std::vector;

int SearchLocalMinima(const vector<int>& sspace) {
        if (sspace.size() < 2)
                return -1;
        if (sspace.size() == 2)
                return 0;
        int L = 0, U = sspace.size() - 1;
        while (L<U) {
                int M = L + (U - L) / 2;
                if (M - 1 == L) {
                        if (sspace[M] <= sspace[M + 1])
                                return M;
                        else
                                return M + 1;
                } else {
                        if (sspace[M] <= sspace[M + 1])
                                U = M + 1;
                        else
                                L = M;
                }

        }
        return -1;
}

int main() {
        vector<int> values{64, 14, 52, 27, 71, 19, 63, 1, 16, 57};
        printf("Local minima: %d\n", SearchLocalMinima(values));
        return 0;
}