题解|《算法竞赛进阶指南》 邻值查找

邻值查找

https://ac.nowcoder.com/acm/contest/1007/A

题目描述
给定一个长度为 n 的序列 A,A 中的数各不相同。对于 A 中的每一个数A_i ,求: ⁡|min(1≤j<i)⁡∣A_i −A_j|
以及令上式取到最小值的 j(记为 P_i )。若最小值点不唯一,则选择使 A_j较小的那个。

输入描述:
第一行一个整数n,第二行n个数A_1~A_n。

输出描述:
n-1行,每行2个用空格隔开的整数。分别表示当i取2~n时,对应的⁡|min(1≤j<i)⁡∣A_i −A_j|和P_i的值。

思路
这是一道有关链表的题(此乃废话)。有多种解法,比如用STL中的set来做。但我们还是用链表来做吧,也不是很难。

时间复杂度分析
因为需要用到sort()所以大概是O(nlogn).

上代码

#include <iostream>
#include <algorithm>

using namespace std;

typedef pair<int, int> PII;

const int N = 1000010;

int n;
PII a[N],ans[N];//一是值,二是下标
int p[N], l[N], r[N];//l[N]是左边的,r[N]是右边的

int main() {
    ios::sync_with_stdio;

    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i].first;
        a[i].second = i;
    }

    sort(a + 1, a + 1 + n);

    a[0].first = 1e9, a[n + 1].first = -1e9;//哨兵
    for (int i = 1; i <= n; i++) {
        l[i] = i - 1;
        r[i] = i + 1;
        p[a[i].second] = i;
    }

    for (int i = n; i > 1; i--) {

        int j = p[i], left = l[j], right = r[j];

        int lv = abs(a[left].first - a[j].first);
        int rv = abs(a[right].first - a[j].first);

        if (lv <= rv) 
            ans[i] = { lv,a[left].second };

        else 
            ans[i] = { rv,a[right].second };

        r[left] = right;
        l[right] = left;
    }
    for (int i = 2; i <= n; i++) 
        cout << ans[i].first << " " << ans[i].second << endl;

    return 0;
全部评论

相关推荐

05-28 23:26
河南大学 Java
双非本,刚学完Redis,项目只有外卖和点评,八股没准备,算法只有lqb省一,感觉敲的项目也是一言难尽没怎么吸收。怎么你们都有实习了
大牛之途:27急个锤子,你投日常实习最好的时间就是9,10月份,那时候暑期实习都结束了,正是缺人的时候。这份日常又能给你的暑期实习增加竞争力,暑期找的好了秋招也不怕了,都是环环相扣的
点赞 评论 收藏
分享
点赞 评论 收藏
分享
05-26 09:07
已编辑
门头沟学院 Java
点赞 评论 收藏
分享
想申请延毕了,找工作找到崩溃,越找就越想摆烂,还有25届的和我一样感受吗?
码农索隆:没事哒,好兄弟,慢慢来,调整心态,车到山前必有路,感到迷茫的时候,多抬头看看
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务