对于某些固定的 N
,如果数组 A
是整数 1, 2, ..., N
组成的排列,使得:
对于每个 i < j
,都不存在 k
满足 i < k < j
使得 A[k] * 2 = A[i] + A[j]
。
那么数组 A
是漂亮数组。
给定 N
,返回任意漂亮数组 A
(保证存在一个)。
示例 1:
输入:4
输出:[2,1,4,3]
示例 2:
输入:5
输出:[3,1,2,5,4]
提示:
1 <= N <= 1000
解题思路
这个问题有一个非常美妙的数学解法。首先我们要证明漂亮数组满足这样几种性质
-
减法(减去一个数仍然是漂亮数组)
( A [ k ] − x ) ∗ 2 = A [ k ] ∗ 2 − 2 ∗ x ≠ ( A [ i ] − x + A [ j ] − x ) (A[k]-x)*2=A[k]*2 - 2*x \neq(A[i] -x + A[j] - x) (A[k]−x)∗2=A[k]∗2−2∗x̸=(A[i]−x+A[j]−x)
-
乘法(乘上一个数仍然是漂亮数组)
A [ k ] ∗ 2 ∗ x ≠ ( A [ i ] + A [ j ] ) ∗ x = A [ i ] ∗ x + A [ j ] ∗ x A[k]*2*x\neq(A[i]+A[j])*x=A[i]*x+A[j]*x A[k]∗2∗x̸=(A[i]+A[j])∗x=A[i]∗x+A[j]∗x
有了上面这两个性质,我们就可以很快解决这个问题了。我们知道一个数组A
可以分为奇数部分A1
和偶数部分A2
。此时我们如果有一个漂亮数组B
,我们根据前面的性质知道2*B-1
是一个漂亮数组并且是奇数数组,而2*B
也是一个漂亮数组并且是偶数数组。那么我们通过2*B+2*B-1
必然可以构成任意一个漂亮数组了。真的非常棒。
class Solution:
def beautifulArray(self, N):
"""
:type N: int
:rtype: List[int]
"""
result = [1]
while len(result) < N:
result = [i * 2 - 1 for i in result] + [i * 2 for i in result]
return [i for i in result if i <= N]
还有一种非常Hacker
的做法,使用的和上面相同的思路。
class Solution:
def beautifulArray(self, N):
"""
:type N: int
:rtype: List[int]
"""
return sorted(range(1, N + 1), key=lambda x: bin(x)[:1:-1])
reference:
https://leetcode.com/problems/beautiful-array/discuss/186679/C++JavaPython-Odd-+-Even-Pattern-O(N)
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!