LeetCode 667——Beautiful Arrangement II

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]
Explanation: The [1, 2, 3] has three different positive integers ranging from 1 to 3, and the [1, 1] has exactly 1 distinct integer: 1.

 

Example 2:

Input: n = 3, k = 2
Output: [1, 3, 2]
Explanation: The [1, 3, 2] has three different positive integers ranging from 1 to 3, and the [2, 1] has exactly 2 distinct integers: 1 and 2.

 

Note:

  1. The n and k are in the range 1 <= k < n <= 10^{4}.

 


 

给出两个参数n和k,n代表数组的长度,并且数组中的元素为从1到n,k的计算遵循以下规则:

假设数组为[a1, a2, a3, ... , an],则计算数组 [|a1 - a2|, |a2 - a3|, ... , |an-1 - an|]中不同数字的个数即为k值。

 

暴力手段在这里我们就不提及了,就是逐个将[1, n]区间内的整数填充到数组中,计算是否满足条件,它的算法时间复杂度将达到O(N!),非常可怕。

我的解题思路和官方解法除法点不太一样,但是最后的处理却比较相似。

思路一(我的解法):

开始我在思考的时候也非常迷茫,因为任意指定的n和k,手动拼凑都要花费一些时间,但是随后我发现,k的最大值为n - 1,也就意味着当n = 6, k = 5时,差值序列就为[1, 2, 3, 4, 5],再进一步的说,差值为5的时候一定是1和6相邻,当只要差值和数组中的一个数字固定的时候,其他的结果就都计算出来了。假设6在最右侧,则对应的原数组就是[3, 4, 2, 5, 1, 6]。

当k为1的时候,差值序列为[1, 1, 1, 1, 5]可以么?答案是肯定的,对应的数组就是 [5, 4, 3, 2, 1, 6]。

那么对于任意的k,我们是不是可以假设差值序列除1外的部分为[n - k, n - k + 1, n - k + 2, ... , n - 1]。那么原数组中的最后一个值也就确定为n,然后根据这些条件求解原数组即可。

在代码实现的时候,我发现执行的代码是可以简化的,仔细观察[3, 4, 2, 5, 1, 6]这个n = 6, k = 5时的序列,其实就是倒序的按照 "two pointer"的方式用两个索引从区间两端交替的不断逼近中间得到的结果。如果k != n - 1,就需要在倒序到达n - k - 1处时,停止一个索引,用另一个索引不断向另一个索引的方向回填结果即可。

这个思路说起来有点抽象,建议配合下边的代码看哦~

 


 

我的解法:

class Solution {
    public int[] constructArray(int n, int k) {
        int[] result = new int[n];
        int left = 1, right = n;
        int i = n - 1;
        boolean isRight = true;
        while (left <= right) {
            if (isRight) {
                result[i--] = right--;
            } else {
                result[i--] = left++;
            }

            if (k > 1) {
                isRight = !isRight;
                --k;
            }

        }

        return result;
    }
}

 


如有错误,欢迎指摘。也欢迎通过左上角的“向TA提问”按钮问我问题,我将竭力解答你的疑惑。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值