优美的排列(力扣第667题)
667.优美的排列
给定两个整数 n 和 k,你需要实现一个数组,这个数组包含从 1 到 n 的 n 个不同整数,同时满足以下条件:
① 如果这个数组是 [a1, a2, a3, ... , an] ,那么数组 [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] 中应该有且仅有 k 个不同整数;.
② 如果存在多种答案,你只需实现并返回其中任意一种.
示例 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
分析:
可以采用连续翻转的方法,比如n=5,即[1,2,3,4,5],
k = 1 1,2,3,4,5
k = 2 1,5,4,3,2
k = 3 1,5,2,3,4
k = 4 1,5,2,4,3
用k=1时的数组作为连续数组,根据k的值决定固定不参与翻转的数为前k-1个,然后剩余的直接进行逆序翻转。
public int[] constructArray(int n, int k) {
int[] res = new int[n];
for (int i = 0; i < res.length; i++) {
res[i] = i+1;
}
for (int i = 2; i <= k; i++) {
swapArray(res,i);
}
return res;
}
private void swapArray(int[] array,int k){
int temp;
int left = k-1;
int right = array.length - 1;
while (left < right){
temp = array[left];
array[left] = array[right];
array[right] = temp;
left++;
right--;
}
}
解法二:还有一种解法参考了cyc2018大神的,就是根据给定的k,让前k+1个元素构建出k个不同的差值,具体的构建方法就是首先定义一个差值变量,初始值为k,从数组第二个元素出发开始遍历,在奇数位置上是,赋值为当前元素的前一个元素值加上这个差值,偶数位置上则是当前元素的前一个位置元素值减去这个差值。每访问一个元素,差值变量减去1,直到前k+1个元素构建完成,然后剩余的元素则是从第k+2个元素出发,直接赋值给这些元素正常的顺序值,也就是索引值加1。
public int[] constructArray(int n, int k) {
int[] ret = new int[n];
ret[0] = 1;
for (int i = 1, interval = k; i <= k; i++, interval--) {
ret[i] = i % 2 == 1 ? ret[i - 1] + interval : ret[i - 1] - interval;
}
for (int i = k + 1; i < n; i++) {
ret[i] = i + 1;
}
return ret;
}