题目
题目描述如下:
- Given two integers n and k, you need to construct a list which contains n different positive integers ranging from 1 to n and obeys the following requirement:Suppose this list is [a1, a2, a3, … , an], then the list [|a1 - a2|, |a2 - a3|, |a3 - a4|, … , |an-1 - an|] has exactly k distinct integers.If there are multiple answers, print any of them.
- Example 1:
Input: n = 3, k = 1
Output: [1, 2, 3]- Example 2:
Input: n = 3, k = 2
Output: [1, 3, 2]
分析
看到这道题的时候,一开始的出发点不正确。我先尝试了n=1~7的各种情况,我的初步判断是为一个动态规划问题,因为欲得到k=m的情况,必先得到k=m-1的情况,然后从后一种情况经过调整变为前一种情况。实践证明,这样解并不是一个很明智的选择,因为这样定义的步骤虽然有规律,但是描述起来比较困难,并且计算机的时间复杂度较高
求解
实现参考“Solution”的思路。一个符合k=m要求的数组可以用两部分组成,第一部分的两项间的差恒定为1,第二部分的二项间的差满足从差的绝对值从2-m。
我们发现当k=1的时候,数组仅需要按自然数排列即可;对于长度为n的情况,当k=n-1的时候。满足条件的数组为[1,n,2,n-1,3,n-2,….]。利用这两条规律。结合第一段的解题思路即可完成本题。具体实现如下:
当输入为n,k的时候,我们将1-n的数组分为两个部分,第一部分为1-(n-k+1),其间距为1;第二部分按照[1,k+1,2,k,3,k-1,….]+(n-k+1)进行赋值,可以保证第二部分的间距为2-k。因为第一部分的结尾与第二分部的开头的差值为1,不会影响两个部分的效果。代码实现如下:1
2
3
4
5
6
7
8
9
10
11
12
13class Solution {
public int[] constructArray(int n, int k) {
int[] ans = new int[n];
int c = 0;
for (int v = 1; v < n-k; v++) {
ans[c++] = v;
}
for (int i = 0; i <= k; i++) {
ans[c++] = (i%2 == 0) ? (n-k + i/2) : (n - i/2);
}
return ans;
}
}
Complexity Analysis
Time Complexity: $O(n)$
Space Complexity: $O(n)$