/*
Sologala @github https://github.com/Sologala/LeetCode.git
LeetCode 667. 优美的排列 II
*/给定两个整数 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
思路:
这道题 需要自己手写几个来寻找规律.
比如上图的 输入 n = 10 , k = 3
最大的 不同的 差 的种类 最大是 k = 3 那么 我们从最大的 差值开始 排列.
默认第一个数字是 1 至于为什么是 1 在最前面呢 ,这是我看他给的答案都是1 开始
从第一个数字开始 找他的下一个数字 next , next = cur +k | cur - k 要不就是当前这个数字 加上一个差值 或者 减去一个差值 . 那么我门寻找这个差值, 默认 先寻找 cur - k 这样可以保证一个数字前面的比他小的数字都有排到 .
反复循环以上的过程 可以排 出 1 4 2 3 当第 5 个数字的时候开始后面都是以 1 为增量的单增的数组.
在观察下面的这个例子:
可以看出 当第 6个数字的时候开始以 1 单增. 那么可以找到一下规律 :
单增的坐标是 x = k+2 , 且之后的每个数字都是前一个数字加 1
于是代码的思路可以如下 :
先按照 前面提到的 规律 排列出 k 种不同的差值的数列.之后在按照单增 1
的规律 排列之后的数字.
**ac_code **
class Solution {
public:
vector<int> constructArray(int n, int k) {
vector<int> ret(1,1);
vector<bool> vis(n+1,false);//标识某个数字是否被使用过
vis[1] = true;
while(k){
int cur = ret[ret.size()-1];
int next = cur - k;//往前找优先
if(next>=1&&next<=n&&vis[next]==false){
ret.push_back(next);
vis[next] = true;
}
else{
next = cur + k;//往后找
if(next>=1&&next<=n&&vis[next]==false){
ret.push_back(next);
vis[next] = true;
}
}
k--;
}
while(ret.size()!= n){//排列之后的 单增的 所有数字
ret.push_back(ret.size()+1);
}
return ret;
}
};