LeetCode - 932. Beautiful Array

932. Beautiful Array

For some fixed N, an array A is beautiful if it is a permutation of the integers 1, 2, ..., N, such that:

For every i < j, there is no k with i < k < j such that A[k] * 2 = A[i] + A[j].

Given N, return any beautiful array A.  (It is guaranteed that one exists.) 1 <= N <= 1000

Input: 4          Output: [2,1,4,3]

Input: 5          Output: [3,1,2,5,4]

解:

    第一反应是从 vecctor<int> res = { 1 }; 开始,一个数一个数往里插,不过看到判断条件是 A[k] * 2 == A[i] + A[j] 就想到,这不是向下取整,所以如果 A[i] + A[j] 一个是奇数一个是偶数(也就是两个的和是奇数),那一定不会有 k 使得 A[k] * 2(偶数) 等于两个数的和,那如果有一个全是奇数的 Beautiful Array(比如叫 Odd ),和一个全是偶数的 Beautiful Array(比如叫 Even ),那这两个拼接起来一定也是 Beautiful Array(因为随机选 i 和 j 的位置,如果都在 Odd 里,或者都在 Even 里,那因为他们两个都是 Beautiful Array 肯定满足条件,如果一边一个,那因为上边的分析,条件也是满足的)。

    如果 N 是奇数(比如 7 ),那就是 Odd 里边有 4 个数(1 3 5 7),Even 里边有三个数(2 4 6);如果 N 是偶数(比如 6 ),那就是 Odd 里边有 3 个数(1 3 5),Even 里边有 3 个数(2 4 6)。最短的 Beautiful Array(N = 1时) 是 { 1 } 这个显而易见。现在要做的就是从基础的 Beautiful Array 一点一点扩展成 N 长度的 Beautiful Array。

    Beautiful Array 有两个很重要的性质可以分析出来:

  • 如果 A 是 Beautiful Array,那么 A * 2 - 1 也是 Beautiful Array(这就变成了全是奇数的 Beautiful Array )
  • 如果 A 是 Beautiful Array,那么 A * 2       也是 Beautiful Array(这就变成了全是偶数的 Beautiful Array )

这样,(A * 2 + 1)和(A * 2)拼接起来,就是 N * 2 长度的 Beautiful Array。每次可以扩充一倍,10次就是 1024 倍,因为题目说了 N <= 1000,那么从 { 1 } 这个 Beautiful Array 到 N = 1000 的 Beautiful Array 就需要 10 次扩充。中间的结果把大于 N 的数删掉就行了。

vector<int> beautifulArray(int N) {
    vector<int> res = { 1 };
    while(res.size() < N)
    {
        vector<int> tmp;
        for(auto r : res)
            if(r * 2 - 1 <= N)
                tmp.push_back(r * 2 - 1);
        for(auto r : res)
            if(r * 2 <= N)
                tmp.push_back(r * 2);
        res = tmp;
    }
    return res;
}

    把每次的结果输出出来,或者手算一下更容易理解:

  • N = 1,res = { 1 }
  • N = 2,res = { 1, 2 }
  • N = 3,res = { 1, 3, 2 }
  • N = 4,res = { 1, 3, 2, 4 }
  • N = 5,res = { 1, 5, 3, 2, 4 }
  • N = 6,res = { 1, 5, 3, 2, 6, 4 }
  • N = 7,res = { 1, 5, 3, 7, 2, 6, 4 }
  • ......

    其实从 { 1, 2 } 开始每次往里插数字应该也是可以的,奇数就在前半部分插,偶数就在后半部分插,不过每次插需要判断插的位置对不对。

猜你喜欢

转载自blog.csdn.net/Bob__yuan/article/details/84241663