C++ 查找数组中第一次出现偶数的索引,运行时成本为O(log(n))
我必须实现一个算法,运行时成本为O(log(n)),该算法在具有以下属性的数组中查找偶数的第一次出现:C++ 查找数组中第一次出现偶数的索引,运行时成本为O(log(n)),c++,arrays,algorithm,time-complexity,C++,Arrays,Algorithm,Time Complexity,我必须实现一个算法,运行时成本为O(log(n)),该算法在具有以下属性的数组中查找偶数的第一次出现: 数组的第一个元素是奇数,接下来的元素是偶数 我不知道有多少元素是奇数,有多少元素是偶数,但我知道至少有一个偶数和一个奇数 我已经写了这个“代码草案”,但工作不正常,有什么改进的建议吗?我认为这个解决方案与我的(我希望)没有太大的不同。 #包括 使用名称空间std; int minInd=1000; 整数f(整数v[],整数开始,整数结束) { int m=结束/2; 如果(v[开始]%2=
- 数组的第一个元素是奇数,接下来的元素是偶数
- 我不知道有多少元素是奇数,有多少元素是偶数,但我知道至少有一个偶数和一个奇数
#包括
使用名称空间std;
int minInd=1000;
整数f(整数v[],整数开始,整数结束)
{
int m=结束/2;
如果(v[开始]%2==0)
如果(开始<最小值)
minInd=开始;
f(v,开始,m);
f(v,m+1,结束);
返回minInd;
}
int main()
{
int v[]={1,3,7,9,5,4,6,8};
int指数=f(v,0,7);
cout您遇到的问题是,您在没有条件的情况下运行了两次f
方法。此外,您的条件应该是检查当前正在处理的给定子数组中间的奇偶校验
你应该这样做:
int f(int v[], int start, int end)
{
int m = (start + end)/2;
if(v[m]%2 == 0) {
if(start == end) {
return start;
} else {
return f(v, start, m);
}
} else {
return f(v, m, end);
}
}
(我没有在这里检查边缘情况等。只是粗略了解逻辑)
@marek-r更新了以下评论有几个问题:
您没有递归的终止条件。
您递归到数组的两半部分,即使添加了终止,也会破坏日志复杂性。
你的细分方法是神秘的,你应该看看中间的元素,然后选择其中的一半。
全局和递归是一种特别令人不快的组合
这是一个常规的二进制搜索,最后有一个小的转折-它首先递归,然后做出决定
int f(int v[], int start, int end)
{
// Terminate when nothing is left.
if (start >= end)
return -1;
// Look at the midpoint.
int mid = start + (end-start) / 2;
// If it's odd, the first even number is to the right.
if (v[mid] % 2 != 0)
{
return f(v, mid + 1, end);
}
// Otherwise, first see if there is any even number to the left.
int left = f(v, start, mid);
// And choose a result depending on whether there was.
return left == -1 ? mid : left;
}
请注意,这使用了传统的半开间隔。size\u t先查找\u偶数(const int v[],int size)
{
返回标准::距离(v,标准::下限(v,v+size,0,
[](自动a,自动b){返回a&1>b&1;});
}
您有一个包含两个分区的数组,奇数值后跟偶数值。标准库算法正是您需要在O(logn)时间内找到第二个分区开始的函数
这段代码基于,我只是认为更多的人应该知道这个稍微模糊的库算法。这是一个简单的二进制搜索问题std::binary_search@ServeLaurijssen不幸的是,std::binary_search
是无用的,因为它返回的是bool
而不是迭代器。此代码不是O(log n)
这个不定式递归。所以基本上你有一个上帝的想法,但你以错误的方式实现了它。请解释“工作不正常”。@MarekR-谢谢。我认为顶层变量是作为解决方案打印出来的。修复了。
int f(int v[], int start, int end)
{
// Terminate when nothing is left.
if (start >= end)
return -1;
// Look at the midpoint.
int mid = start + (end-start) / 2;
// If it's odd, the first even number is to the right.
if (v[mid] % 2 != 0)
{
return f(v, mid + 1, end);
}
// Otherwise, first see if there is any even number to the left.
int left = f(v, start, mid);
// And choose a result depending on whether there was.
return left == -1 ? mid : left;
}
size_t find_first_even(const int *v, int size)
{
auto itr = std::partition_point(v, v + size, [](int value) { return value & 1; });
return std::distance(v, itr);
}