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

本文介绍了如何解决一个编程问题,即给定两个整数n和k,构造一个列表,使得列表中相邻元素的差值有k个不同整数。文章通过示例和解析解题思路,展示了如何通过无序和有序排列组合来构建这样的数组,并提供了具体的代码实现。
摘要由CSDN通过智能技术生成

一、题目

给你两个整数 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去构造有序排列了。如下所示:

四、代码实现

class Solution {
    public int[] constructArray(int n, int k) {
        int interval = k;
        int[] answer = new int[n];
        answer[0] = 1;
        for (int i = 1; i <= k; i++) {
            answer[i] = i % 2 == 1 ? answer[i - 1] + interval : answer[i - 1] - interval;
            interval--;
        }
        for (int i = k + 1; i < n; i++) {
            answer[i] = i + 1;
        }
        return answer;
    }
}

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

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

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值