0932-漂亮数组
如果长度为 n 的数组 nums 满足下述条件,则认为该数组是一个 漂亮数组 :
nums是由范围[1, n]的整数组成的一个排列。- 对于每个
0 <= i < j < n,均不存在下标k(i < k < j)使得2 * nums[k] == nums[i] + nums[j]。
给你整数 n ,返回长度为 n 的任一 漂亮数组 。本题保证对于给定的 n 至少存在一个有效答案。
示例 1 :
**输入:** n = 4
**输出:** [2,1,4,3]
示例 2 :
**输入:** n = 5
**输出:** [3,1,2,5,4]
提示:
1 <= n <= 1000
方法一:分治
分析
首先我们可以发现一个不错的性质,如果某个数组 [a_1, a_2, \cdots, a_n] 是漂亮的,那么对这个数组进行仿射变换,得到的新数组 [ka_1+b, ka_2+b, \cdots, ka_n+b] 也是漂亮的(其中 k \neq 0)。那么我们就有了一个想法:将数组分成两部分 left 和 right,分别求出一个漂亮的数组,然后将它们进行仿射变换,使得不存在满足下面条件的三元组:
A[k] * 2 = A[i] + A[j], i < k < j;A[i]来自left部分,A[j]来自right部分。
可以发现,等式 A[k] * 2 = A[i] + A[j] 的左侧是一个偶数,右侧的两个元素分别来自两个部分。要想等式恒不成立,一个简单的办法就是让 left 部分的数都是奇数,right 部分的数都是偶数。
因此我们将所有的奇数放在 left 部分,所有的偶数放在 right 部分,这样可以保证等式恒不成立。对于 [1..N] 的排列,left 部分包括 (N + 1) / 2 个奇数,right 部分包括 N / 2 个偶数。对于 left 部分,我们进行 k = 1/2, b = 1/2 的仿射变换,把这些奇数一一映射到不超过 (N + 1) / 2 的整数。对于 right 部分,我们进行 k = 1/2, b = 0 的仿射变换,把这些偶数一一映射到不超过 N / 2 的整数。经过映射,left 和 right 部分变成了和原问题一样,但规模减少一半的子问题,这样就可以使用分治算法解决了。
算法
在 [1..N] 中有 (N + 1) / 2 个奇数和 N / 2 个偶数。我们将其分治成两个子问题,其中一个为不超过 (N + 1) / 2 的整数,并映射到所有的奇数;另一个为不超过 N / 2 的整数,并映射到所有的偶数。
1 | class Solution { |
1 | class Solution: |
复杂度分析
时间复杂度:O(N \log N),代码中的函数
f执行的次数为 O(\log N),每次执行的时间复杂度为 O(N)。空间复杂度:O(N \log N)。