• 图解LeetCode——667. 优美的排列 II(难度:中等)


    一、题目

    给你两个整数 n 和 k ,请你构造一个答案列表 answer ,该列表应当包含从 1 到 n 的 n 个不同正整数,并同时满足下述条件:

    假设该列表是 answer = [a1, a2, a3, ... , an] ,那么列表 [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] 中应该有且仅有 k 个不同整数。

    返回列表 answer 。如果存在多种答案,只需返回其中 任意一种 。

    二、示例

    2.1> 示例 1:

    【输入】n = 3, k = 1
    【输出】[1, 2, 3]
    【解释】[1, 2, 3] 包含 3 个范围在 1-3 的不同整数,并且 [1, 1] 中有且仅有 1 个不同整数:1

    2.2> 示例 2:

    【输入】n = 3, k = 2
    【输出】[1, 3, 2]
    【解释】[1, 3, 2] 包含 3 个范围在 1-3 的不同整数,并且 [2, 1] 中有且仅有 2 个不同整数:1 和 2

    提示:

    • 1 <= k < n <= 10^4

    三、解题思路

    根据题目描述,方法入参由两个参数,第一个参数是n,我们可以得到一个数组[1, 2, 3, 4, ... , n]。第二个参数是k,表示当我们遍历数组,计算相邻两个元素的差值(取绝对值)的时候,有且仅有k个不同的整数。那么,针对这个数组,差值一共能有多少种情况呢?我们以下图为例,给出一个数组[1, 2, 3, 4, 5, 6],我们发现,一共能获得5中不同的差值。那么,我们其实可以得出一个结论,一个长度为n的数组,其差值就在[1, n-1]的区间内,详情如下图所示:

    我们得出如下结论之后,那么,下面步骤,就是要根据k的值,具体安排这n个数在数组中的位置了。我们以n=6,k=3为例。首先,因为1是数组中最小的值。所以我们将数组中第一位的值赋值为1,然后我们根据以1为基准,在去安排其他值。

     确定了数组中第一个值为1之后,我们来安排一下其他元素,根据第一张图,我们可以得知,如果数组中的元素是按照顺序排列的话,每个相邻节点的差值就是1,所以,这就是我们得出的第1个差值。那么针对于第二个参数k值。我们就可以将整个数组分为两部分排列:无顺序排列 + 有顺序排列。类似如下这种情况:

     所以,我们先来看一下无顺序排列的情况,我们的目的,是要拼装出k-1种差值。这种情况的拼装方式就需要一个interval变量了。它表示要“跳跃”的区间,最初我们可以将其赋值为k的值,即:interval = k;由于k等于3,所以interval=3。首先,我们要先向前跳跃3个区间,即:4,这个值就是我们数组中的第二个值,并且,由于我们需要不同的差值,此时interval要减1,即:interval=2。然后,我们要向后跳跃2个区间,即:2,这个值就是我们数组中的第三个值。一次类推。最终,我们得到数组[1, 4, 2, 3, ...]。此时的差值为:3,2,1。即:满足了k=3的约束了。

    那么,在最后,我们只需要将有序排列的数组构建出来就可以了。由于跳跃区间interval我们初始化为k,并且上面只构建了数组中前k+1个元素的,这里面除去1之外最小值为:minValue = 2,最大值为:maxValue = k + 1。而我们当前的下标是i,i = maxValue + 1;所以假设answer[i]=i,则answer[i]与minValue的差值等于 (maxValue + 1) - 2 = ( k + 1 + 1) - 2 = k。而k值已经包含在了前[0, i -1]的数组区间内了。那么,我们就可以直接通过answer[i] = i + 1去构造有序排列了。如下所示:

    四、代码实现

    1. class Solution {
    2.     public int[] constructArray(int n, int k) {
    3.         int interval = k;
    4.         int[] answer = new int[n];
    5.         answer[0= 1;
    6.         for (int i = 1; i <= k; i++) {
    7.             answer[i] = i % 2 == 1 ? answer[i - 1+ interval : answer[i - 1] - interval;
    8.             interval--;
    9.         }
    10.         for (int i = k + 1; i < n; i++) {
    11.             answer[i] = i + 1;
    12.         }
    13.         return answer;
    14.     }
    15. }

    今天的文章内容就这些了:

    写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享 。

    更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」

  • 相关阅读:
    MyBatis模糊查询
    kubectl别名配置
    Java.lang ClassLoader findClass()方法具有什么功能呢?
    《安卓安装包管理后台》——前端Vue3源码部署
    Vue Grid Layout -️ 适用Vue.js的栅格布局系统,在vue3+上使用
    MyBatis-Plus 和swagger
    vant3的option写法示例(部分组件:swipe、popup、picker、stepper、field、tab、tabbar)
    Linux环境下Qt应用程序打包与发布
    bash: /usr/bin/cp: Argument list too long Linux 系统大量数据移动复制出错
    MySQL必知必会-笔记-Part3
  • 原文地址:https://blog.csdn.net/qq_26470817/article/details/126760838