LC 667. 优美的排列 II
题目描述
这是 LeetCode 上的 667. 优美的排列 II ,难度为 中等。
给你两个整数 n
和 k
,请你构造一个答案列表 answer
,该列表应当包含从 1
到 n
的 n
个不同正整数,并同时满足下述条件:
假设该列表是 $answer = [a1, a_2, a_3, … , a_n]$ ,那么列表 $[|a_1 - a_2|, |a_2 - a_3|, |a_3 - a_4|, … , |a{n-1} - a_n|]$ 中应该有且仅有 k
个不同整数。
返回列表 answer
。
如果存在多种答案,只需返回其中 任意一种 。
示例 1:1
2
3
4
5输入:n = 3, k = 1
输出:[1, 2, 3]
解释:[1, 2, 3] 包含 3 个范围在 1-3 的不同整数,并且 [1, 1] 中有且仅有 1 个不同整数:1
示例 2:1
2
3
4
5输入:n = 3, k = 2
输出:[1, 3, 2]
解释:[1, 3, 2] 包含 3 个范围在 1-3 的不同整数,并且 [2, 1] 中有且仅有 2 个不同整数:1 和 2
提示:
- $1 <= k < n <= 10^4$
构造
给定范围在 $[1, n]$ 的 $n$ 个数,当「直接升序/降序」排列时,相邻项差值为 $1$,仅一种;而从首位开始按照「升序」间隔排列,次位开始按照「降序」间隔排列(即排列为 [1, n, 2, n - 1, 3, ...]
)时,相邻差值会从 $n - 1$ 开始递减至 $1$,共 $n - 1$ 种。
那么当我们需要构造 $k$ 种序列时,我们可以先通过「直接升序」的方式构造出若干个 $1$,然后再通过「间隔位分别升降序」的方式构造出从 $k$ 到 $1$ 的差值,共 $k$ 个。
显然,我们需要 $k + 1$ 个数来构造出 $k$ 个差值。因此我们可以先从 $1$ 开始,使用 $n - (k + 1)$ 个数来直接升序(通过方式一构造出若干个 $1$),然后从 $n - k$ 开始间隔升序排列,按照 $n$ 开始间隔降序排列,构造出剩下的序列。
Java 代码:1
2
3
4
5
6
7
8
9
10
11
12class Solution {
public int[] constructArray(int n, int k) {
int[] ans = new int[n];
int t = n - k - 1;
for (int i = 0; i < t; i++) ans[i] = i + 1;
for (int i = t, a = n - k, b = n; i < n; ) {
ans[i++] = a++;
if (i < n) ans[i++] = b--;
}
return ans;
}
}
C++ 代码:1
2
3
4
5
6
7
8
9
10
11
12
13class Solution {
public:
vector<int> constructArray(int n, int k) {
vector<int> ans(n);
int t = n - k - 1;
for (int i = 0; i < t; ++i) ans[i] = i + 1;
for (int i = t, a = n - k, b = n; i < n; ) {
ans[i++] = a++;
if (i < n) ans[i++] = b--;
}
return ans;
}
};
Python 代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14class Solution:
def constructArray(self, n: int, k: int) -> List[int]:
ans = [0] * n
t = n - k - 1
for i in range(t):
ans[i] = i + 1
i, a, b = t, n - k, n
while i < n:
ans[i] = a
i, a = i + 1, a + 1
if i < n:
ans[i] = b
i, b = i + 1, b - 1
return ans
TypeScript 代码:1
2
3
4
5
6
7
8
9
10function constructArray(n: number, k: number): number[] {
const ans = new Array<number>(n).fill(0)
const t = n - k - 1
for (let i = 0; i < t; i++) ans[i] = i + 1
for (let i = t, a = n - k, b = n; i < n; ) {
ans[i++] = a++
if (i < n) ans[i++] = b--
}
return ans
};
- 时间复杂度:$O(n)$
- 空间复杂度:$O(n)$
最后
这是我们「刷穿 LeetCode」系列文章的第 No.667
篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!