数组题目:优美的排列 II

题目

标题和出处

标题:优美的排列 II

出处:667. 优美的排列 II

难度

7 级

题目描述

要求

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

  • 假设该列表是 answer = [ a 1 , a 2 , a 3 , … , a n ] \texttt{answer} = [\texttt{a}_\texttt{1}, \texttt{a}_\texttt{2}, \texttt{a}_\texttt{3}, \ldots, \texttt{a}_\texttt{n}] answer=[a1,a2,a3,,an],那么列表 [ ∣ a 1 − a 2 ∣ , ∣ a 2 − a 3 ∣ , ∣ a 3 − a 4 ∣ , … , ∣ a n-1 − a n ∣ ] [|\texttt{a}_\texttt{1} - \texttt{a}_\texttt{2}|, |\texttt{a}_\texttt{2} - \texttt{a}_\texttt{3}|, |\texttt{a}_\texttt{3} - \texttt{a}_\texttt{4}|, \ldots, |\texttt{a}_\texttt{n-1} - \texttt{a}_\texttt{n}|] [a1a2,a2a3,a3a4,,an-1an] 中应该有且仅有 k \texttt{k} k 个不同整数。

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

示例

示例 1:

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

示例 2:

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

数据范围

  • 1 ≤ k < n ≤ 10 4 \texttt{1} \le \texttt{k} < \texttt{n} \le \texttt{10}^\texttt{4} 1k<n104

解法

思路和算法

为了方便叙述,将列表 [ ∣ a 1 − a 2 ∣ , ∣ a 2 − a 3 ∣ , ∣ a 3 − a 4 ∣ , … , ∣ a n − 1 − a n ∣ ] [|a_1 - a_2|, |a_2 - a_3|, |a_3 - a_4|, \ldots, |a_{n-1} - a_n|] [a1a2,a2a3,a3a4,,an1an] 称为「相邻绝对差列表」。

对于从 1 1 1 n n n 的任意排列,对应的「相邻绝对差列表」中的不同整数最少为 1 1 1 个,即所有的相邻元素绝对差都相等,最多为 n − 1 n-1 n1 个,即所有的相邻元素绝对差都不相等。

对于列表 [ 1 , 2 , 3 , … , n ] [1, 2, 3, \ldots, n] [1,2,3,,n],「相邻绝对差列表」中的元素都是 1 1 1,因此有 1 1 1 个不同整数。

对于列表 [ 1 , n , 2 , n − 1 , 3 , n − 2 , … ] [1, n, 2, n - 1, 3, n - 2, \ldots] [1,n,2,n1,3,n2,],「相邻绝对差列表」中的元素各不相同,分别为 n − 1 n-1 n1 1 1 1,因此有 n − 1 n-1 n1 个不同整数。

为了让「相邻绝对差列表」中的不同整数为 k k k 个,可以从整数 1 1 1 k + 1 k+1 k+1 构造出「相邻绝对差列表」中的元素各不相同的序列: [ 1 , k + 1 , 2 , k , 3 , k − 1 , … ] [1, k + 1, 2, k, 3, k - 1, \ldots] [1,k+1,2,k,3,k1,],然后将从 k + 2 k+2 k+2 n n n 的整数依次添加到该序列的末尾。

按照上述方法构造出的序列,前 k + 1 k+1 k+1 个数的相邻元素绝对差各不相同,分别为 k k k 1 1 1,从 k + 2 k+2 k+2 n n n 的相邻元素绝对差都是 1 1 1 k + 2 k+2 k+2 前面的相邻元素一定大于 1 1 1,因此 k + 2 k+2 k+2 和前面的相邻元素的绝对差一定不超过 k k k。即整个序列的「相邻绝对差列表」包含从 1 1 1 k k k 的全部整数,且不包含大于 k k k 的整数,因此「相邻绝对差列表」中有且仅有 k k k 个不同整数。

证明

对于列表 [ 1 , n , 2 , n − 1 , 3 , n − 2 , … ] [1, n, 2, n - 1, 3, n - 2, \ldots] [1,n,2,n1,3,n2,],「相邻绝对差列表」中的元素各不相同,分别为 n − 1 n-1 n1 1 1 1,有 n − 1 n-1 n1 个不同整数。该结论证明如下。

arr \textit{arr} arr 表示列表 [ 1 , n , 2 , n − 1 , 3 , n − 2 , … ] [1, n, 2, n - 1, 3, n - 2, \ldots] [1,n,2,n1,3,n2,],则 arr \textit{arr} arr 中的每个下标对应的元素如下:

arr [ i ] = { i 2 + 1 , i   是 偶 数 n − i − 1 2 , i   是 奇 数 \textit{arr}[i]=\begin{cases} \dfrac{i}{2}+1, & i~是偶数 \\ n-\dfrac{i-1}{2}, & i~是奇数 \end{cases} arr[i]=2i+1,n2i1,i i 

1 ≤ i < n 1 \le i < n 1i<n 时, arr [ i ] − arr [ i − 1 ] \textit{arr}[i]-\textit{arr}[i-1] arr[i]arr[i1] 计算如下:

  • i i i 是奇数时:

  arr [ i ] − arr [ i − 1 ] = ( n − i − 1 2 ) − ( i − 1 2 + 1 ) = n − ( i − 1 ) − 1 = n − i \begin{aligned} &\quad \ \textit{arr}[i]-\textit{arr}[i-1] \\ &= \Big(n-\dfrac{i-1}{2}\Big)-\Big(\dfrac{i-1}{2}+1\Big) \\ &= n-(i-1)-1 \\ &= n-i \end{aligned}  arr[i]arr[i1]=(n2i1)(2i1+1)=n(i1)1=ni

  • i i i 是偶数时:

  arr [ i − 1 ] − arr [ i ] = ( n − i − 2 2 ) − ( i 2 + 1 ) = n − ( i 2 − 1 ) − i 2 − 1 = n − i 2 + 1 − i 2 − 1 = n − i \begin{aligned} &\quad \ \textit{arr}[i-1]-\textit{arr}[i] \\ &= \Big(n-\dfrac{i-2}{2}\Big)-\Big(\dfrac{i}{2}+1\Big) \\ &= n-\Big(\dfrac{i}{2}-1\Big)-\dfrac{i}{2}-1 \\ &= n-\dfrac{i}{2}+1-\dfrac{i}{2}-1 \\ &= n-i \end{aligned}  arr[i1]arr[i]=(n2i2)(2i+1)=n(2i1)2i1=n2i+12i1=ni

由于 1 ≤ i < n 1 \le i < n 1i<n,因此 1 ≤ n − i ≤ n − 1 1 \le n-i \le n-1 1nin1 arr \textit{arr} arr 对应的「相邻绝对差列表」中的元素各不相同,分别为 n − 1 n-1 n1 1 1 1

代码

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

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)。构造数组 answer \textit{answer} answer 的过程为遍历该数组一次,填入每个元素的时间为 O ( 1 ) O(1) O(1),因此时间复杂度为 O ( n ) O(n) O(n)

  • 空间复杂度: O ( 1 ) O(1) O(1)。除了返回值以外,使用的空间复杂度是常数。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟大的车尔尼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值