在LeetCode上的旅程开始了,一步步慢慢溜达吧!
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.)
Example 1:
Input: 4
Output: [2,1,4,3]
Example 2:
Input: 5
Output: [3,1,2,5,4]
Note:
1 <= N <= 1000
题目大意:生成一个完美序列A。完美序列的定义:完美序列的长度为N,且都由1~N组成。在序列中对于任意的两个数 A[j] ,A[i],不存在 k(j < k < i) 使得 2*A[k] == A[j]+A[i]。
解题思路:这个的解题思路很有趣。首先很容易就能得到一个最简单的完美序列 [1] ,然后,对于每一个长度为 N 的完美序列都可以分成两部分,左边都是 个偶数,右边都是
个奇数。(倒过来也行)因为在奇数和偶数之间必然符合条件。其次,假设已经存在一个完美序列 a 对于任意 i , j , k 都符合 2*a[k] != a[i] + a[j] ,则有两种魔改方式可以保证等式任然成立。魔改一:不等式两边同时加 2*x (x是任意整数) 即: 2*a[k] + 2*x != (a[i] + x) + (a[j] + x) ; 魔改2:不等式两边同时乘 y (y是任意整数)即:2*(a[k]*y) != a[i]*y + a[j]*y。接下来就是关键步骤了,我们可以将一个长度为 n 的完美序列 a 通过将序列中的每个元素都乘2 并减 1得到一个序列 a1 ,在将完美序列 a 中的每个元素都乘2得到一个序列 a2 。(序列a1,a2序列中的每个元素都符合要求。)其中,再将两个序列进行拼接就能得到一个长度为 2*n 的完美序列A。因为序列 a1 中的每个元素恰好是 序列 A 中的所有奇数,序列a2 中的每个元素恰好是序列 A 中的所有偶数。如果需要长度为 2*n - 1 的完美序列则在A的基础上去掉数字 2*n 即可。(这个数字不一定是最后一个数字。)按照这个思路的时间复杂度是 O(nlogn)。
我自己的AC代码(递归)8ms:
class Solution {
public:
vector<int> GetDealArray(vector<int> & array){
vector<int> ans;
for(auto i : array){ //将序列中的所有元素都乘2
ans.push_back(i*2);
}
for(auto & i : array){
//将序列中的所有元素都乘2减1,
//这个序列通过引用返回
i = i*2 - 1;
}
return ans; //函数返回的是乘2得到的序列
}
vector<int> DeepConstructArray(int len_array){
if(len_array == 1){
return vector<int>(1,1);
}
//得到一个长度为N/2的完美序列
vector<int> get1 = DeepConstructArray((len_array + 1)/2);
vector<int> get2 = GetDealArray(get1); //将得到后的序列进行魔改
vector<int> get3;
get3.insert(get3.end(),get1.begin(),get1.end()); //魔改后的序列组成一个新的序列
if(len_array&1){
for(auto & i : get2){
if(i <= len_array){
get1.push_back(i);
}
}
}else{
get1.insert(get1.end(),get2.begin(),get2.end());
}
return get1;
}
vector<int> beautifulArray(int N) {
vector<int> ans = DeepConstructArray(N);
return ans;
}
};
在看完通过后看了看别人的代码,即使是一样的思路。但是完全就是有不一样的效果。
class Solution {
public:
vector<int> beautifulArray(int N) {
vector<int> ans = {1}; //最基本的完美序列
while(ans.size() < N){
vector<int> array; //将原序列进行魔改并且拼接
for(auto i : ans){
if(i*2 - 1 <= N)
array.push_back(2*i - 1);
}
for(auto i : ans){
if(2*i <= N)
array.push_back(2*i);
}
ans = array;
}
return ans;
}
};
不得不说相对来说LeetCode还是比较休闲的。