一道思维题(有意思)

U431308 Maximum-Gap

给你一个序列 a,求它排完序后的 max(|aiai1|),其实就是求一个序列排完序后的相邻元素的最大差值。
样例:
输入: n=4,a=[11,2,7,5]
输出: 4
请你在不使用任何排序,值域很大的情况下以 O(n) 的复杂度解决这个问题。
有想法可以在评论区留言🤓️🤓️
大概在晚上公布一下原贴地址。
这题是最大间隙问题,出自codeforces的讨论 The smartest stupid problem that you might see today
这道题如果值域可以接受的话,就可以使用桶排,是个经典的 hard 面试题,好几个网站(比如 LeetCode)上都有,但这个没啥意思。CSacademy 上有原 Consecutive Max Difference

undate on 5.14
考虑找一个数 x,使得 x 最大且 xans,不难发现 x=maxminn1 时满足条件,所以我们按值域,以 x 为块长分个块,然后将每个元素一次入块,更新块内的最大值最小值,答案就是两个邻接的块中,这个块的最小值减去上一个块的最大值,取 max 即可。
这题还有个毒瘤题目 P4604 [WC2017] 挑战
可以有另一种做法,转进制后用基数排序,几乎是 O(n) 的,感觉非常牛逼。

const int N = 2e7 + 10;
int n;
long long a[N], t_max[N], t_min[N], maxn = 0, minn = 2e18;
unsigned long long seed;
bool vis[N];
signed main() {
int t;
cin >> t;
cin >> seed;
Seed(seed);
while (t--) {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
memset(t_max, 0, sizeof(t_max));
memset(t_min, 0x7f, sizeof(t_min));
memset(vis, 0, sizeof(vis));
maxn = 0, minn = 2e18;
for (int i = 1; i <= n; ++i) a[i] = Rand(), maxn = max(maxn, a[i]), minn = min(minn, a[i]);
long long x = (maxn - minn) / (n - 1) - 1;
long long tot = 0;
for (int i = 1; i <= n; ++i) {
long long pos = (a[i] - minn - 1) / x + 1;
tot = max(pos, tot);
vis[pos] = 1;
t_max[pos] = max(t_max[pos], a[i]);
t_min[pos] = min(t_min[pos], a[i]);
}
long long last = t_min[1], ans = 0;
for (int i = 1; i <= tot; ++i) {
if (vis[i]) {
ans = max(t_min[i] - last, ans);
last = t_max[i];
}
}
cout << ans << '\n';
}
}
posted @   Ishar-zdl  阅读(75)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示