[ch1301]邻值查找--链表

给定一个长度为 n 的序列 A,A 中的数各不相同。对于 A 中的每一个数 A_i,求:
min(1≤j<i) ⁡|A_i-A_j|

以及令上式取到最小值的 j(记为 P_i)。若最小值点不唯一,则选择使 A_j 较小的那个

 进阶指南的例题,一开始没看懂写法。

题意大概是,给一个数列,对其中每一项,在前面所有项中找到一个数,与它的差的绝对值最小。(因此要求n-1个值,即除了第一项)

大致做法是,以最后一位为对象开始查找,那么此时它前面所有的数都是可以拿来用的,而这个时候用一个链表,来将数列排序之后链接在一起。

此时对链表每一项a_n,a_n-1和a_n+1其中必然有一个是和它的差绝对值最小的那一个项,但是,这两个项可能在原数列中不是在a_n的前面,也就是说,不合法。但如果是原数列中最后一项,那么此时链表中所有值都合法,然后,找出此项结果,把该项在链表中删除,可以删除,就意味着这一项对链表其他项寻找结果不会有影响,因为在原数列中它在所有项后面,必然不能取,因此结论成立,此时再找剩下的在原数列中最后一项,数学归纳法得出。

做出这题,一来是会这种类似于高等代数中的对式子的变型处理,二来是会写这个链表。真的很不好写。。。数据的对应,比较难处理。这题我错在两个地方,一个是读错题意,输出错了数据,而来是将链表的head和tail在排序之前赋值,然后和其他数值一起排序导致出错,这题我对数据的处理显然是很不得当,再接再厉把。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=100010;
int tot,n,head,tail,q;
struct node{
	int x,y;
	int val,next,pre;
}a[maxn];
void initialize()
{
	tot=2;head=1,tail=2;
	a[head].next=tail;
	a[tail].pre=head;
	//cout<<endl<<endl<<a[2].pre<<endl;
}
void insert(int p,int v)
{
	q=++tot;
	//cout<<tot<<endl;
	a[q].val=v;
	a[a[p].next].pre=q;
	a[q].next=a[p].next;
	a[p].next=q;
	a[q].pre=p;
}
void move(int p)
{
	a[a[p].pre].next=a[p].next;
	a[a[p].next].pre=a[p].pre;
}
bool cmp(const node &a,const node &b)
{
	return a.x<b.x;
}
int b[maxn],c[maxn];
vector < pair<int,int> >vec;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].x;
		a[i].y=i;
	}
	sort(a+1,a+1+n,cmp);
	initialize();
	int t=1;
	//cout<<a[2].pre<<endl;
	for(int i=1;i<=n;i++){
		insert(t,a[i].x);
		b[a[i].y]=tot;
		c[tot]=a[i].y;
		t=tot;
	}
	/*for(int i=1;i<=n+2;i++){
		//printf("pos=%d,a[pos].pre=%d,a[pos].next=%d\n\n",i,a[i].pre,a[i].next);
	}*/
	for(int i=n;i>1;i--){
		int pos=b[i];//i=3,pos=4;
		//cout<<i<<" "<<pos<<endl;
		int px=a[pos].pre,nx=a[pos].next;
		//cout<<px<<" "<<nx<<endl;
		//printf("pos=%d\n\n",pos);
		//printf("px=%d,nx=%d\n",px,nx);
		if(nx==tail){
			vec.push_back(make_pair(abs(a[pos].val-a[px].val),c[px]));
			//cout<<abs(a[pos].val-a[px].val)<<" "<<a[px].val<<endl;
		}else if(px==head){
			vec.push_back(make_pair(abs(a[pos].val-a[nx].val),c[nx]));
			//cout<<abs(a[pos].val-a[nx].val)<<" "<<a[nx].val<<endl;
		}else if(abs(a[pos].val-a[px].val)<=abs(a[nx].val-a[pos].val)){
			vec.push_back(make_pair(abs(a[pos].val-a[px].val),c[px]));
			//cout<<abs(a[pos].val-a[px].val)<<" "<<a[px].val<<endl;
		}else{
			vec.push_back(make_pair(abs(a[pos].val-a[nx].val),c[nx]));
			//cout<<abs(a[pos].val-a[nx].val)<<" "<<a[nx].val<<endl;
		}
		move(pos);
		/*if(c[px]==0){
			cout<<"reme: "<<px<<" "<<"px"<<endl;
		}else if(c[nx]==0){
			cout<<"reme: "<<nx<<" "<<"nx"<<endl;
		}*/
	}
	for(int i=vec.size()-1;i>=0;i--){
		cout<<vec[i].first<<" "<<vec[i].second<<endl;
	}
	return 0;
}

不得不说数据结构的题目写起来很繁琐。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值