MarsCode 错题本
51 和的逆运算
这题在给定的和不重复的情况下很简单:
- 首先升序排序好数组sums,生成答案数组
nums[n]
。 nums[0] + nums[1]
必然等于sums[0]
(最小值),nums[0] + nums[2]
必然等于sums[1]
(次小值), … ,nums[n-2] + nums[n-1]
必然等于sums[lastIndex]
(最大值)。- 可以反向推测出
nums[0] = (sums[0] + sums[1] - sums[n-1]) / 2
,论证看下方:
nums[n] = {a, b, c, d, e} 从小到大排列 |
- 得出了
nums[0]
,其他数字都可以用nums[i] = sums[i-1] - nums[0]
推出来
但是给定的和重复的情况下,上面的第2条就不成立了。例如测试用例3:
sums[] = { 223, 224, 225, 225, 226, 226, 227, 227, 228, 229 } |
在给定的和有重复元素的情况下,我们再按照上面的步骤1排序好数组sums,算出来的nums[0]
就是错误的,因为这个时候b+c < a+e
,a+e
排到了b+c
的位置,再套用步骤3的算法就不对了。
综上所述,重新整理后我们会发现,排序数组不是目的。真正的目的是能够让数组符合步骤3的公式nums[0] = (sums[0] + sums[1] - sums[n-1]) / 2
,让b+c
能够正确地出现在sums[n-1]
的位置。
可是,我们并没有原数组,怎么做的出来呢?
数学家思维:给定一个有序的数组nums,其中元素按升序排列,一定存在一个有序两两和序列sums。
找到这个有序两两和序列,就可以根据上面的算法反推出原来的数组。
我不知道有没有一种数学算法可以优雅地找到有序两两和序列sums,一举这个问题。但是全排列一定能找到这个sums。以下是第51题的全部代码:
import java.util.Arrays; |