Sorted Adjacent Differences(CodeForces - 1339B)【思维+贪心】
B - Sorted Adjacent Differences(CodeForces - 1339B)
算法
思维+贪心
时间复杂度O(nlogn)
1.这道题的题意主要就是让你对一个数组进行一种特殊的排序,使得数组中相邻的两个数的差的绝对值成非递减趋势;
2.刚开始对这道题总是执拗于两个相等的数在不同位置,如何把它们放到前面
这个问题,因为路走歪了,最终无果,没有思路。后来看了一些关于这道题的解题博客,豁然开朗。
3.使得数组中相邻的两个数的差的绝对值成非递减趋势,怎么想呢。单纯想怎么从差的绝对值最小到最大变化不太容易想,我们可以反过来想,怎么由差的绝对值最大到最小变化。什么时候差的绝对值最大,当然是数组中的最小值和最大值之间的差的绝对值最大。最小值和次大值之间的差的绝对值大
还是最小值和次小值之间的差的绝对值大
(或者最大值和次小值的差的绝对值大
还是最大值和次大值的绝对值大
),当然是前者。
4.然后在想接下来可能再小的是什么,当然是次小值和次大值之间的差的绝对值。以此类推,可以的出下面这个式子。
最小值、最大值、次小值、次大值、第三小值、第三大值、...
或者
最大值、最小值、次大值、次小值、第三大值、第三小值、...
注意上面的式子只是为了好理解才按照这个顺序写的,最终输出的时候不要忘了把它倒过来(不知道为啥请看题意)。
5.列出了式子后,那么思考一下什么时候才到头呢,即到哪里结束呢?
对于偶数个数的数组来讲,即最终达到处于中间的那两个数;
对于奇数个数的数组来讲,即最终到达处于中间的那一个数。
所以要特判一下。这也是为什么前面一开始就说要将题意倒过来想,否则直接想出从中间向两边展开这个思路不太容易。
6.所以最终得出的思路是先对数组排序,然后从中间向两边展开输出。
C++代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int t, n;
int a[N];
int main()
{
cin >> t;
while(t--)
{
cin >> n;
for(int i = 0; i < n; i++)
cin >> a[i];
sort(a, a + n);
/*
n = 5
0,1,2,3,4
n = 4
0,1,2,3
*/
int l, r;
if(n % 2 == 1)
{
cout << a[n/2] << " ";
l = n / 2 - 1, r = n / 2 + 1;
}
else
l = n / 2 - 1, r = n / 2;
while(l >= 0 && r < n)
{
//cout << a[r] << " " << a[l] << " ";
cout << a[l] << " " << a[r] << " ";
//上面这两个式子用哪个都可以
++r;
--l;
}
puts("");
}
return 0;
}