Medium
题目描述
给定两个整数 n 和 k,构造一个答案列表 answer,该列表应当包含从 1 到 n 的 n 个不同正整数,并同时满足下述条件:
假设该列表是 answer = [a1, a2, a3, … , an],那么列表 [|a1 - a2|, |a2 - a3|, |a3 - a4|, … , |an-1 - an|] 中应该有且仅有 k 个不同的整数。
返回列表 answer。如果存在多种答案,只需返回其中任意一种。
示例 1:
输入:n = 3, k = 1
输出:[1,2,3]
解释:[1,2,3] 包含 3 个范围在 1-3 的不同正整数,并且 [1,1] 中有且仅有 1 个不同的整数:1
示例 2:
输入:n = 3, k = 2
输出:[1,3,2]
解释:[1,3,2] 包含 3 个范围在 1-3 的不同正整数,并且 [2,1] 中有且仅有 2 个不同的整数:1 和 2
提示:
1 <= k < n <= 10^4
解题思路
这道题的关键在于理解如何构造出恰好有 k 个不同差值的数组。
核心观察:
- 如果数组是连续递增的(如[1,2,3,4,5]),那么所有相邻差值都是1,只有1个不同差值
- 如果数组在最大值和最小值之间交替(如[1,5,2,4,3]),可以产生多种不同的差值
解法思路: 采用"交替构造"的策略:
- 先放置前 k+1 个数字,通过在最小值和最大值之间交替来产生 k 个不同的差值
- 剩余的数字按顺序排列,确保它们的差值都是1(已经包含在前面的差值中)
具体步骤:
- 使用 low = 1, high = k+1 进行交替放置
- 第一次放 low,第二次放 high,第三次放 low+1,第四次放 high-1…
- 这样可以产生差值:k, k-1, k-2, …, 1
- 最后将剩余数字 [k+2, k+3, …, n] 按顺序添加
这种方法保证了恰好有 k 个不同的差值,且构造过程简单高效。
代码实现
class Solution {
public:
vector<int> constructArray(int n, int k) {
vector<int> result;
int low = 1, high = k + 1;
// 交替放置前k+1个数字,产生k个不同差值
for (int i = 0; i < k + 1; i++) {
if (i % 2 == 0) {
result.push_back(low++);
} else {
result.push_back(high--);
}
}
// 按顺序添加剩余数字
for (int i = k + 2; i <= n; i++) {
result.push_back(i);
}
return result;
}
};
class Solution:
def constructArray(self, n: int, k: int) -> List[int]:
result = []
low, high = 1, k + 1
# 交替放置前k+1个数字,产生k个不同差值
for i in range(k + 1):
if i % 2 == 0:
result.append(low)
low += 1
else:
result.append(high)
high -= 1
# 按顺序添加剩余数字
for i in range(k + 2, n + 1):
result.append(i)
return result
public class Solution {
public int[] ConstructArray(int n, int k) {
int[] result = new int[n];
int low = 1, high = k + 1;
int index = 0;
// 交替放置前k+1个数字,产生k个不同差值
for (int i = 0; i < k + 1; i++) {
if (i % 2 == 0) {
result[index++] = low++;
} else {
result[index++] = high--;
}
}
// 按顺序添加剩余数字
for (int i = k + 2; i <= n; i++) {
result[index++] = i;
}
return result;
}
}
var constructArray = function(n, k) {
const result = [];
let low = 1, high = k + 1;
for (let i = 0; i <= k; i++) {
if (i % 2 === 0) {
result.push(low++);
} else {
result.push(high--);
}
}
for (let i = k + 2; i <= n; i++) {
result.push(i);
}
return result;
};
复杂度分析
| 复杂度类型 | 值 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历构造n个数字 |
| 空间复杂度 | O(1) | 除了返回数组外,只使用常数额外空间 |
相关题目
- . Beautiful Arrangement (Medium)