邻值查找

题目(邻值查找)

给定一个长度为 n 的序列 A,A 中的数各不相同。对于 A 中的每一个数 Ai,求:
min|Ai−Aj|1≤j<i)以及令上式取到最小值的 j(记为 Pi)。若最小值点不唯一,则选择使 Aj 较小的那个。
输入格式

第一行输入整数n,代表序列长度。
第二行输入n个整数A1…An,代表序列的具体数值,数值之间用空格隔开。

输出格式

输出共n-1行,每行输出两个整数,数值之间用空格隔开。

分别表示当i取2~n时,对应的min|Ai−Aj|1≤j<i)和Pi的值。

数据范围

n≤1e5,
|Ai|≤1e9

输入样例:

3
1 5 3

输出样例:

4 1
2 1

思路:

将原序列排序后串成一个链表,本题麻烦就麻烦在链表编号和原序列编号,以及左指针右指针之间的关系。而且得从原序列中的第n个元素开始往前找,不然就很麻烦,之前就是从中间开始往两边找,极其麻烦。

代码:

#include<iostream>
#include<algorithm>
#include<climits>
#include<cmath>
using namespace std;
typedef pair<int,int> PII;
const int N=100010;
PII a[N],res[N];//a[N]存储原序列,res[N]存储答案
int L[N],R[N],pos[N];//链表左指针右指针以及链表中元素的位置与其原序列中的位置对应关系
int r;//计数器
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i].first;
        a[i].second=i;
    }
    sort(a+1,a+n+1);
    a[0].first=INT_MIN;
    a[n+1].first=INT_MAX;//避免处理边界问题
    for(int i=1;i<=n;i++)
    {
        pos[a[i].second]=i;
        L[i]=i-1;
        R[i]=i+1;
    }//将链表中位置关系左指针右指针对应起来
    int position,left1,right1;
    for(int i=n;i>=2;i--)//本题是从第n个元素开始找,这样就避免了从中间开始双向找的麻烦,我之前就是双向找然后情况太多debug不出来啊啊啊
    {
        position=pos[i];
        left1=L[position];
        right1=R[position];
        if(abs(a[position].first-a[left1].first)<=abs(a[right1].first-a[position].first)) 
        {
            res[++r].first=abs(a[position].first-a[left1].first);
            res[r].second=a[left1].second;
        }
        else  
        {
            res[++r].first=abs(a[right1].first-a[position].first);
            res[r].second=a[right1].second;
        }
        R[left1]=right1;
        L[right1]=left1;//删除节点
    }
    for(int i=r;i>=1;i--)
    cout<<res[i].first<<" "<<res[i].second<<endl;//倒着从2-n输出答案
    return 0;
}

本题还有一种方法但是我没学,见书P61

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值