LeetCode破解之优美排列

106 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情

题目描述

给你两个整数 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

数学技巧

写着写着就觉得这到题目越来越像一个规律题目了,而且也很好找到其中的规律。使用k+1个数字,即可组成k个差值,剩余的部分直接使用差值为1顺序填充即可。如[1, 1**+k**, 1+k**-(k-1), 1+k-(k-1)+(k-1-1)**,,,]

  • 构造让前k+1个元素并且构造出 k 个不同的差值 ,序列为 1,k+1,2,k,3,k-1,...,k/2,k/2+1。比如这里n=6,k=3 那么前4个元素构造成3个不同的差值 即前四个元素为 1 4 2 3 差值为 3 2 1
  • 途中也继续构造后面n-(k+1)个元素 这里接着上面的 1 4 2 3 添加 5 6 构造成 1 4 2 3 5 6
  • 最后直接返回结果数组就好。这道题感觉是一个找规律的题。
class Solution {
    public int[] constructArray(int n, int k) {
        int[] ints = new int[n];

        int i = 0;
        while (true){
            if (i==0 && i+k<=n){
                for (; i < k+1;i++) {
                    if (i%2==0)ints[i] = i/2+1;
                    else ints[i] = k+1-i/2;
                }
            }else {
                while(i!=n) {
                    ints[i] = i + 1;
                    i++;
                }
                break;
            }
        }
        return ints;
    }
}

最后

题目我不想说什么,我感觉这个字符串并不怎么优美。核心思想就是贪心,有k个数便能构成k-1种差,所以取最后k个数来建立,而且每次将最后面的数翻转到前面时,最终的数组会增加2种差为不同值的情况。因为数组天然的差值为1种(即是1)所以假设要翻转a个后面的数插入到前面,那么a = (k - 1) / 2。这样最终的种类数就会是2a+1个。所以如果k是偶数的情况下,我们要翻转最后两个数,增加一种差的可能。然后贪着贪着发现题目是有规律的。