【问题标题】:Is this modern programming interview challenge's solution unreliable?这个现代编程面试挑战的解决方案不可靠吗?
【发布时间】:2015-11-08 20:08:17
【问题描述】:

所以我没有通过编程面试题,就像

"给定一个整数数组 1, 2, ..., n,其中一个缺失,求 丢失的那个。”

面试官说正确答案是把数字相加,然后从n(n+1)/2中减去和,即套用公式https://en.wikipedia.org/wiki/1_%2B_2_%2B_3_%2B_4_%2B_%E2%8B%AF

并说任何计算机科学专业的学生都会这样做。我的解决方案是

char takenSpots [] = n*malloc(sizeof(char)); 
for (int k = 0; k < n; ++k) takenSpots[arr[k]-1] = 'x';
for (int k = 0; k < n; ++k) if (takenSpots[k] != 'x') return (k+1);

这不像我承认我从未想过尝试的求和解决方案那么“酷”。

首先,使用求和法是不是有溢出的危险?我的意思是,如果 arr 包含 ~((int)0)~((int)0) - 1 怎么办?那么arr[0] + arr[1] + ... + arr[n-1] 不会溢出吗?或者由于1 + 2 + ... + n 也溢出,该解决方案仍然有效?

【问题讨论】:

  • for(i = 1; i &lt; n; i++){ if(arr[i - 1] != arr[i] - 1){ printf("Found it: %i\n", arr[i] - 1); } } 还是我对问题的解释有误?
  • char takenSpots [] = n*malloc(sizeof(char)); 是几个编译器错误。
  • @Kninnug:从问题中可能不清楚,但想法是整数不一定按顺序排列。
  • 好吧,你绝对应该从初始化takenSpots数组中的所有条目开始!
  • 为什么会更快?平均 n/2 次比较,n 次最坏情况。如果你假设你有 1 到 n 一个缺失,你可以在 O (log n) 中进行二分查找。现在 that 更快了。

标签: c algorithm optimization integer time-complexity


【解决方案1】:

确实,面试官提出的解决方案会溢出。事实上,有一个更好的解决方案不会出现溢出问题,如果你提出了求和方案,面试官可能会跟进。

更好的解决方案不那么直观,但据我所知,它如今已广为人知。

它依赖于以下内容:

x xor y = y xor x
x xor 0 = x
x xor x = 0

因此,更好的解决方案是计算所有给定数字的异或,然后用从1n 的所有数字的异或进行异或。出现在您的数组中的那些将与从1n 的那些抵消。丢失的那个会留下来。

至于如何考虑这样的解决方案,没有秘诀。您只需熟悉此类挑战/面试问题,并接受过计算机科学和数学方面的培训。

不要因为没有得到它而感到难过。如果我在大学毕业之前没有看到这个问题,我几乎肯定不会在面试环境中得到求和解决方案(我可能最终在我自己的时间里弄明白了),我绝对不会想出 xor没有先看到它的解决方案。这类问题几乎是命中注定的。如果它很成功,他们可能会问其他问题,直到你不知道答案为止。

他们这样做不是为了让你措手不及。他们这样做是为了看看你是怎么想的,通常:你能想出一个幼稚的解决方案(你做到了),你能说出它有什么问题吗?你能想出改进它的方法吗,也许是朝着正确的方向轻推?你能解释一下你将如何研究更好的解决方案吗?思考过程可能比解决方案更重要。

如果面试官只说你的解决方案很糟糕,而你应该知道更好的解决方案(我不认为在完成专业后你必须绝对了解 X 的事情清单在 X) 中,您应该寻找更好的工作场所。

【讨论】:

  • 不知道这个解决方案。非常聪明:)
  • 值得注意的是 XOR[1..n] = 0 if n%4==0n-1 if n%4==11 if n%4==2n if n%4==3
  • 这个 XOR 解决方案只是另一个提醒我,编程绝对是一剂艺术与科学。数字中的某种诗意。
【解决方案2】:

如果您使用无符号整数,使用公式的方法仍然有效,因为 C 标准为乘法和加法指定了模运算。使用 n 位整数,您可以保证获得模 2^n 的正确结果,并且由于您知道结果必须在 0-2^n 范围内,因此您知道它必须是正确的。

【讨论】:

  • 你确定吗?在模运算中如何除以 2?
  • 你是对的,你必须更加小心,在乘法之前(即在需要模算术之前)将 n 或 n+1(哪个是偶数)除以 2跨度>
  • 如果你小心地这样做(注意 (a + b) % c = (a % c + b % c) % c 和同样适用于乘法,但不适用于除法: (a / b) % c != ((a % c) / (b % c)) % c)`,这应该可行。如果你在测试语言知识,这比我认为的 xor 解决方案更有价值。
【解决方案3】:

几乎所有计算机科学专业的学生都应该解决它。他的解决方案在 O(n) 时间和 O(1) 空间中运行,您的解决方案在 O(n) 时间中运行,具有更大的常数和 O(n) 空间。所以他的解决方案更好也就不足为奇了。

关于溢出。几乎任何问题你都可以想出会溢出的输入。如果你听到“如何将两个数字相加”的问题,然后看到解决方案 a + b,它也会遭受溢出。或者输出你从输入中得到的数字也会溢出。

面试中的一个好主意是询问您期望什么样的意见。当你提出解决方案时,你必须说明你会遇到什么样的问题。如果总和小于 X,我将两个数字相加。如果您想要更好,请使用 big int 算术。

P.S.你有没有想过当n太高时你可能没有足够的内存来进行malloc操作?

【讨论】:

  • 我没有投反对票,但我不同意“几乎所有计算机科学专业的学生都应该解决它”。这是一个需要数学知识或熟悉此类问题的问题,而这在许多编程工作中并不一定需要。他们不会在大学 AFAIK 中教这些东西。
  • @IVlad,感谢您的意见。但我认为数学知识是CS学生应该已经具备的,应用于CS或在学习期间发展。如果一个人不知道如何对从 1 到 n 的数字求和,很难想象他将如何分析 qsort 或 dijkstra 的复杂性。但我同意,很难说 CS 学生能做什么和不能做什么,这就是我添加“几乎”的原因。这意味着在 100 个 CS 人员中,我预计有 90 个知道它,并且会认为有 10 个还没有准备好接受一份工作。
  • 我认为这不一定是不知道这些事情的问题,而是确定问题需要它们并将它们放在一起的问题。有人可能知道 xor 做什么,但我敢打赌,如果他们以前没有听说过 xor 解决方案,大多数知道 xor 是什么的人都不会想出 xor 解决方案。了解各个元素是一回事,而能够分辨出它们可以应用于给定问题是另一回事。对于后者,您需要有关此类问题的知识,而这些知识在正式的 CS 学习 AFAIK 期间并没有真正开发出来。
【解决方案4】:

这是一道数学题,不是编程题。我不确定计算机科学专业的学生是否参加了包含系列的数学课程,如果没有,那么如果程序员以前遇到过这种情况,那就有点随机了。还有其他系列,例如 power 系列,作为许多 http://en.wikipedia.org/wiki/List_of_mathematical_series 的一部分。

这些问题在什么时候不再是编程问题和数学问题?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-16
    • 2014-08-12
    • 2017-10-03
    • 2020-01-16
    • 1970-01-01
    • 2022-06-10
    • 2017-08-19
    • 1970-01-01
    相关资源
    最近更新 更多