Acwing4211. 序列重排
Posted 卷王2048
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Acwing4211. 序列重排相关的知识,希望对你有一定的参考价值。
Acwing4211. 序列重排
给定一个长度为 n 的整数序列 a 1 , a 2 , … , a n a1,a2,…,an a1,a2,…,an。
请你对序列进行重新排序(也可以保持原序列),要求新序列满足每个元素(第 1 个除外)都恰好是前一个元素的两倍或前一个元素的三分之一。
保证输入一定有解。
输入格式
第一行包含整数 n。
第二行包含 n 个整数 a 1 , a 2 , … , a n a1,a2,…,an a1,a2,…,an。
输出格式
一行 n 个整数,表示排序后的序列。输出任意合法方案即可。
数据范围
前三个测试点满足
2
≤
n
≤
10
2≤n≤10
2≤n≤10
所有测试点满足$ 2≤n≤100$,
1
≤
a
i
≤
3
×
1
0
18
1≤ai≤3×10^18
1≤ai≤3×1018
输入样例1:
6
4 8 6 3 12 9
输出样例1:
9 3 6 12 4 8
输入样例2:
4
42 28 84 126
输出样例2:
126 42 84 28
输入样例3:
2
1000000000000000000 3000000000000000000
输出样例3:
3000000000000000000 1000000000000000000
思路
昨天刚回家,没来得及打周赛,晚上把题做了一下,早上起来看视频和题解的时候发现自己的做法和题解和视频都
有点激动,第一次自己的解法和大家的都不一样
首先要想清楚这个序列中必然没有重复的数字
看到数据范围立刻意识到可以暴力模拟
题目保证一定有解,枚举每一个数作为答案序列的第一个数,如果找不到就跳过,找到了就直接输出
利用unordered_map
把每一次查找优化为
o
(
1
)
o(1)
o(1)
注意:题目中的三分之一一定要加一步整除的判断
被这个小粗心折磨了20分钟55555
题解
时间复杂度: o ( n 2 ) o(n^2) o(n2)
#include "bits/stdc++.h"
using namespace std;
const int N = 105;
typedef long long LL;
LL a[N];
//用map可以优化查找过程,并且标记这个数有没有被选过
unordered_map<LL,bool> s;
int n;
int main()
cin>>n;
for(int i = 0; i <n; i++)
cin>>a[i];
s.insert(a[i], true);
for(int i = 0; i <n; i++)
//枚举每个数作为首位
LL first = a[i];
//存下每一次的答案
vector<LL> ans;
//初始化,清空所有标记
for(auto &x: s)
x.second = false;
//将第一个数加进去
ans.push_back(first);
//只要有存在合条件,且没有用过的数,就一直往后加
while ((s.count(first *2)&&!s[first *2])||(first %3==0&&s.count(first /3)&&!s[first /3]))
if (s.count(first *2)&&!s[first *2])
ans.push_back(first *2);
//标记这个数为用过
s[first *2] = true;
first = first *2;
else if (first %3==0&&s.count(first /3)&&!s[first /3])
ans.push_back(first /3);
s[first /3] = true;
first = first /3;
//如果所有数都加进去了,说明找到了答案
if (ans.size()==n)
for(int j = 0; j <n; j++)
cout<<ans[j]<<' ';
break;
以上是关于Acwing4211. 序列重排的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode - 143 - 重排链表 - Java - 两种解法 - 细致