我刚刚接受了一个关于我如何设计一个简单函数的面试问题 - 在Int数组中找到第二大数字。
int findSecondLargest(int * arr, int len){
int second = 0;
...
return second;
}
然而,我被问及以下有关如何处理这些问题的问题。
我真的感到困惑。我认为不可能处理所有情况。我们通常必须记录函数的用法,而不是抛出异常。
希望得到一些建议。感谢//函数体由我自己编写。我非常喜欢Donotalo和PigBen所设想的设计
答案 0 :(得分:11)
遵循标准库模型,在搜索序列时,我们不返回我们要查找的值,我们返回一个迭代器到该值(在这种情况下是一个指针)。如果我们没有找到值,我们将迭代器返回到最后一个元素之后,签名将如下所示:
// end is not the last element, it is one past the last element
int * findSecondLargest(int * begin, int * end);
答案 1 :(得分:2)
面试官是否给出了职能机构?如果没有,我会编写一个函数,返回数组中第二大项的索引。如果找不到第二大项(如错误情况),我的函数将返回len
以指示找不到第二大项。
答案 2 :(得分:1)
返回'特殊值'(例如0)的问题是,数组中的第二大数字可能为0.你怎么能分辨出来?
写入的函数无法使用它的返回值来指示何时发生错误。您可以重构它以返回错误代码并使用out参数填充找到的值(非常C风格),或者您可以抛出异常(更多C ++风格)。
编辑:
我刚刚发现,如果返回的值是数组中第二大数字的索引,则可以使用负数作为“特殊值”。
答案 3 :(得分:0)
具体使用该功能并不排除处理角落情况。它只是意味着您在这种情况下明确记录了函数的行为。
您是否抛出异常或返回特定(魔术)值取决于您。您可能还会要求更改返回类型,以便您可以进行更丰富的诊断。
在任何情况下,考虑整个投入领域都是一种好习惯。例如,您在这里也忘记了将arr
NULL
或len
视为否定的情况。
答案 4 :(得分:0)
使用GCC特定的变量数args-to-macro表示法仅用于测试,但无论如何,基本思想是:
如果len小于2(我想我们可以返回一个特殊值,如0或MinInt。)
但是,如果第二大是0(因为在这种情况下,我无法区分错误和正常返回值。所以我可能会抛出异常)
合理输入的例外非常糟糕!
如果数组是{1,1,1}(因为1是最大的数字,不是第二大数。所以我可能会抛出异常)
这是有争议的,但这是我建模的行为,也是通过返回NULL。
所以:
代码有点杂乱,但FWIW:
#include <iostream>
template <typename T, int N>
T* second_largest(T (&arr)[N])
{
if (N < 2) return NULL;
T* largest = &arr[0];
T* second = NULL;
for (int i = 1; i < N; ++i)
{
if (arr[i] > *largest)
{
second = largest;
largest = &arr[i];
}
else if (arr[i] != *largest && (!second || arr[i] > *second))
second = &arr[i];
std::cout << "i " << i << ", largest " << (largest ? *largest : -1)
<< ", second " << (second ? *second : -1) << '\n';
}
return second;
}
#define TEST(ASSERTION, ARRAY...) \
{ \
int x[] = { ARRAY }; \
int* p = second_largest(x); \
assert(ASSERTION); \
std::cout << #ASSERTION << " passed for " << #ARRAY << '\n'; \
}
int main()
{
TEST(*p == 4, 1, 3, 2, 5, 4, 0);
TEST(!p, 1, 1, 1);
TEST(!p, 1);
TEST(*p == 1, 1, 2);
TEST(*p == 1, 2, 1);
TEST(*p == 1, 1, 2, 0);
std::cout << "all tests passed\n";
}