C 查找数组中先增大后减小的最大元素
我做了一个代码,为下面的输入编译,它是正确的 作为 产量:500C 查找数组中先增大后减小的最大元素,c,algorithm,data-structures,binary-search,C,Algorithm,Data Structures,Binary Search,我做了一个代码,为下面的输入编译,它是正确的 作为 产量:500 Input: arr[] = {1, 3, 50, 10, 9, 7, 6} 产量:50 int findIncre_Decre(int arr[], int low, int high) { if (low == high) return arr[low]; /* If there are two elements and first is greater then
Input: arr[] = {1, 3, 50, 10, 9, 7, 6}
产量:50
int findIncre_Decre(int arr[], int low, int high)
{
if (low == high)
return arr[low];
/* If there are two elements and first is greater then
the first element is maximum */
if ((high == low + 1) && arr[low] >= arr[high])
return arr[low];
/* If there are two elements and second is greater then
the second element is maximum */
if ((high == low + 1) && arr[low] < arr[high])
return arr[high];
int mid = (low + high)/2; /*low + (high - low)/2;*/
/* If we reach a point where arr[mid] is greater than both of
its adjacent elements arr[mid-1] and arr[mid+1], then arr[mid]
is the maximum element*/
if ( arr[mid] > arr[mid + 1] && arr[mid] > arr[mid - 1])
return arr[mid];
if (arr[mid] > arr[mid + 1] && arr[mid] < arr[mid - 1])
return findIncre_Decre(arr, low, mid-1);
else
return findIncre_Decre(arr, mid + 1, high);
}
预期产量:-
15
但我得到的答案是16而不是15
任何想法都将不胜感激
提前感谢。为什么它会起作用?编写代码时假设数组可以分为两部分:一部分是递增部分,另一部分是递减部分。此测试用例打破了先决条件 您可以检查数组是否有效,但在最坏的情况下,需要进行线性扫描。最好是简单地检查每个元素,以找到最大的元素 举个例子,检查输入是否正确并不总是好的。对于这个特殊的问题,如果您想在O(logN)中解决它,就必须假设输入是正确的
(edit:为了公平起见,这个答案被编辑了。在原始答案中,我给了OP一个测试用例,以帮助他们找到代码失败的地方,但我的测试用例也是无效的。)正如@Rafael Giusti在编写程序时所说的,我们也必须尝试捕获无效输入 我已经添加了错误处理问题的解决方案(无效情况下数组中的最大元素)。上述问题可以通过以下方式解决:
int findElement(int arr[], int low, int high) {
if(low < 0 || low >= high || low+1 == high) return (arr[low] < arr[high] ? arr[high] : arr[low];
int max = arr[low];
for(int i=low+1; i<=high-1 && low-1 <= high; i++) {
max = arr[i] > max ? arr[i] : max;
if(arr[i-1] < arr[i] && arr[i] > arr[i+1])
return arr[i]; //Perfect match !!
}
return max; // We haven't found any element
}
int-findElement(int-arr[],int-low,int-high){
如果(低<0 | |低>=高| |低+1==高)返回(arr[low]
二进制搜索方法
注意:在数组输入无效的情况下返回最大值
int findElement(int arr[], int low, int high) {
if(high < low) return arr[low];
if(high-low < 2) return (arr[low] > arr[high]) ? arr[low] : arr[high];
int mid = (low + high)/2;
int left = findElement(arr, low, mid-1);
int right = findElement(arr, mid+1, high);
return (left < arr[mid]) && (right < arr[mid]) ? arr[mid] : (left > right ? left : right);
}
int-findElement(int-arr[],int-low,int-high){
if(高<低)返回arr[低];
如果(高-低<2)返回(arr[low]>arr[high])?arr[low]:arr[high];
int mid=(低+高)/2;
int left=findElement(arr、low、mid-1);
int right=findElement(arr,中+1,高);
返回(左右?左:右);
}
你的问题是数组会先增大然后减小…但是你的输入数组有随机数的集合…似乎是矛盾的!它不起作用,因为输入数组不适合先增大然后减小的条件。@MBo抱歉,我知道了,谢谢你。你的数组y不应包含随机数。示例中的16不合适。使用此设置,只需在随机数组中查找最大的数即可(因为最大的数将被较小的数包围,这意味着它在该特定部分先增大后减小)。这只是一个线性搜索;只有当你很好地了解数组的属性时,你才能进行一种形式的二元搜索。如果它先增大后减小,没有任何偏差,二元搜索就可以正常工作。这个答案是错误的。线性版本只搜索递增/递减序列的边界。它不会在OP自己的测试用例!当简单的线性扫描和OP的版本适用于小到1的数组时,它还要求数组的大小为3。检查无效输入的唯一方法是运行整个数组,依次验证每个元素。如果数组几乎正确,则任何其他替代方法都将失败,但在某些部分违反了规则,即算法决定不验证,因为它放弃了第一个或没有分支。@giusti线性搜索只验证了两种无效情况,例如1)对于这个问题,数组大小必须最小为3;2)如果序列在整个过程中增加,或3)给定序列在整个过程中减少)。对于像随机数序列这样的情况,这将不会验证-对于这种情况,您必须遍历整个数组来验证输入数组。此外,这不是线性搜索的精确实现。我们正在使用线性搜索来解决我们的问题。在这里,我们添加了验证标准,比如搜索应该只适用于最小长度为3的数组。希望你能理解……我能理解。但是,只验证一些测试用例对您来说没有多大意义。如果序列是{1,0,-1,4}
,则代码返回-1
;如果序列是{1,2,-1,4}
,则代码返回-2
。两者都是无效的输入,但是如果用户信任您的函数,他们会认为其中一个是有效的。您应该以一致的方式验证和检测错误,或者在假设输入有效的情况下让算法运行。@giusti用户已经给了一个正数数组(我的示例接受并返回正数)。如果他/她在数组中有负数,则他们必须使用其他值来验证无效案例。。
int findElement(int arr[], int low, int high) {
if(low < 0 || low >= high || low+1 == high) return (arr[low] < arr[high] ? arr[high] : arr[low];
int max = arr[low];
for(int i=low+1; i<=high-1 && low-1 <= high; i++) {
max = arr[i] > max ? arr[i] : max;
if(arr[i-1] < arr[i] && arr[i] > arr[i+1])
return arr[i]; //Perfect match !!
}
return max; // We haven't found any element
}
int findElement(int arr[], int low, int high) {
if(high < low) return arr[low];
if(high-low < 2) return (arr[low] > arr[high]) ? arr[low] : arr[high];
int mid = (low + high)/2;
int left = findElement(arr, low, mid-1);
int right = findElement(arr, mid+1, high);
return (left < arr[mid]) && (right < arr[mid]) ? arr[mid] : (left > right ? left : right);
}