题目链接:C-排序_牛客练习赛116 (nowcoder.com)
本题需要出题目的描述中得到许多有效的结论,其一最重要的结论就是某个数x是否能变得更小取决于后面有没有x-1,当然就算有还需要知道能否移动到这个位置上来,这时候就需要判断在x-1到x的位置移动路径上有没有数字的阻挡,也就是路径上有没有除x-2和x之外的数字的存在。那么如果按照这个思路暴力的话一定会超时,这时候只需要用10个队列去保存每个数的各个下标(小的放前面)。如果在x-2和x之外的数字出现在路径上就不能移动直接保存。
当然还需要用一个哈希数组来记录某些下标下的数是否已经被使用过了,如果使用过了自然也是不能用的。在判断某个数满足的时候也需要从队列里面弹出。
还需要注意0和9进行特殊判断:
a=(now-1+10)%10,b=(now+1)%10;
这两个取余就是对0和9的特殊判断。
官方答案:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e7+10;
char s[N],t[N];
bool vis[N];
queue<int> Q[10];
bool check(int idx) {
	if (Q[idx].empty()) return false;
	for (int i=0; i<=9; i++) {
		int val=abs(i-idx);
		if (val==1||val==9||i==idx) continue;
		if (Q[i].empty()) continue;
		if (Q[i].front()<Q[idx].front()) return false;
	}
	return true;
}
void Set(int idx, int u) {
	t[idx]='0'+u;
	vis[Q[u].front()]=true;
	Q[u].pop();
}
int main() {
	int T; cin>>T;
	while (T--) {
		cin>>s;
		int n=strlen(s);
		for (int i=0; i<n; i++) Q[s[i]-'0'].push(i),vis[i]=false;
		int i=0,tot=0;
		while(i<n) {
			int now=s[i]-'0';
			int a=(now-1+10)%10,b=(now+1)%10;
			if (a>b) swap(a,b);
			if (a<now&&check(a)) Set(tot,a);
			else if (b<now&&check(b)) Set(tot,b);
			else Set(tot,now);
			tot++;
			while (vis[i]) i++;
		}
		t[tot]='\0';
		cout<<t<<'\n';
	}
	return 0;
}
/*
86754321
78563412
*/