667 Beautiful Arrangement II
Given two integers n
and k
, you need to construct a list which contains n
different positive integers ranging from 1
to n
and obeys the following requirement:
Suppose this list is [a1, a2, a3, ... , an], then the list [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] has exactly k
distinct integers.
If there are multiple answers, print any of them.
Example 1:
Input: n = 3, k = 1
Output: [1, 2, 3]
Explanation: The [1, 2, 3] has three different positive integers ranging from 1 to 3, and the [1, 1] has exactly 1 distinct integer: 1.
Example 2:
Input: n = 3, k = 2
Output: [1, 3, 2]
Explanation: The [1, 3, 2] has three different positive integers ranging from 1 to 3, and the [2, 1] has exactly 2 distinct integers: 1 and 2.
Note:
The
n
andk
are in the range 1 <= k < n <= 104.
其实跟526 Beautiful Arrangement毫无瓜葛。我一开始还brute force了,结果不出所料直接TLE了。然后想了半天没想出来怎么弄,就只能看答案了。其实这题是要找规律,直接生成数字。因为要判断差,所以brute force不能优化,要一直递归到底找到答案为止。
其实,这一题是可以这样生成:譬如,n = 6, k = 3, 我们有[1, | 2, 3, 4, 5, 6],我们可以把[2, 3, 4, 5, 6]翻转,得到一个diff。[1, 6, | 5, 4, 3, 2],然后再翻转,得到第二个diff,[1, 6, 2, 3, 4, 5],如此类推,翻转k次以后就得到k个diff了。但这个方法要翻转很多次,所以可能要O(n2)
这里规律是,从[1,n]的数组,最多可以生成的k个diff是[n - 1],[1, n, 2, n-1, 3, n-2, ....].最少的k是1.[1, 2, 3, ..., n]。知道这个规律以后,我们就可以把答案分成两段,一段是k-1的升序片段,另一段能产生最大diff的n - k。譬如,n = 6, k = 3, 我们有[1, 2, 3, 4, 5, 6],那么我们就可以生成[1, 2, | 3, 6, 4, 5]或者[1, 6, | 2, 3, 4, 5]。具体做法是,当k是基数时,从左边取数,当k时偶数时,从右边开始取数(可能是因为这是递增序列)。T:O(n)
public int[] constructArray(int n, int k) {
int[] res = new int[n];
if (n < 1 || k < 1) {
return res;
}
int i = 1;
int j = n;
int index = 0;
while (i <= j) { // 判断何时停止加数
if (k > 1) {//最后的一个diff是递增序列的,所以k - 1是条件
if (k % 2 == 1) {//基数从头开始取
res[index++] = i++;
} else {//偶数从尾巴开始取
res[index++] = j--;
}
k--;//每次产生一个diff,k要减一
} else {
res[index++] = i++;//最后的diff是递增序列产生的
}
}
return res;
}
Last updated
Was this helpful?