题目链接:
题目大意:
给定整数 n, k 满足 1 <= k < n <= 104, 找出区间 [1, n] 上所有整数组成的一个序列(长度为 n, 各项不相同), 使得: 该序列上所有相邻两项间的差的绝对值所组成的集合上只有 k 项;
例如: 给定 n = 3, k = 1, 则输出应为: [1, 2, 3] ;
又例: 给定 n = 3, k = 2, 则输出应为: [1, 3, 2] ;
解题过程:
(1) 为求简单, 考虑找出一种通用模式, 即: 对任意输入, 试图使得题设中的绝对值组成的集合(下称 S)中的各项恰为 1, 2, ..., k ;
(2) 在此基础上, 为实现 (1), 需要搞定 k+1 个数, 而对于剩下的 n-(k+1) 个数, 最简单的处理可以是: 其为连续的 n-(k+1) 个数;
(3) 因此, 考虑问题: 对给定的区间 [1, k+1], 是否可以使区间中的 k+1 个各异的整数组成一个序列 A, 使得该序列对应的 S 中的各项也恰为 1, 2, ..., k ;
(a) 显然, 最大项和最小项 (也即 1 和 k+1) 必须相邻, 且, 有且只有一对相邻项 A[i], A[i+1] 满足 | A[i] - A[i+1] | == 1 ;
(b) 故考虑: 序列 A 形式上为 由 1, k+1 相邻项的极大差距 逐渐过渡到 x, x+1 的极小差距, 也即, 摆动数列 的形式: 1, k+1, 2, k, 3, k-1, ... ;
(4) 于是, 剩下的 k+2, k+3, ..., n, 只需要顺序排列即可; 而 k+2 与 前一项的差距必然不大于 k ;
代码如下:
vector< int >
constructArray( int n, int k ) {
int a = 1;
int b = 1 + k;
vector< int > ret;
for ( ; a <= b; a++, b-- ) {
ret.push_back( a );
if ( a == b ) {
break;
}
ret.push_back( b );
}
for ( int i = ( 1 + k ) + 1; i <= n; i++ ) {
ret.push_back( i );
}
return ret;
}
Runtime: 26 ms