邻值查找(0x13 链表与邻接表)

简介: 笔记

邻值查找


题意

给定一个长度为 n的序列 A ,A 中的数各不相同。


对于 A 中的每一个数 A i ,求:


m i n 1 ≤ j < i ∣ A i − A j ∣


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


思路

将原数组按照权值递增排序后,构造成一个链表,然后按照输入顺序从后往前计算结果,每算出一个数 A i 的结果后,就将其从链表中删除,这样可以保证计算第 i 个数时,所有还存在的数在输入中一定在其前面 满足了题目要求的 1<=j<i


实现细节请看代码注释


代码

#include<bits/stdc++.h>
#define int long long
#define INF 0x3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define rep(i, st, ed) for (int (i) = (st); (i) <= (ed);++(i))
#define pre(i, ed, st) for (int (i) = (ed); (i) >= (st);--(i))
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
template<typename T> inline T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<typename T> inline T lowbit(T x) { return x & -x; }
const int N = 1e5 + 10;
int n;
PII a[N]; // 记录每个数的权值和输入的下标
PII res[N]; // 记录答案
int p[N]; // 记录每个数排序后的下标
int l[N], r[N]; // 前向指针和后向指针数组
void solve() {
  cin >> n;
  rep(i, 1, n) {
    cin >> a[i].first; // 读入权值
    a[i].second = i; // 记录下标
  }
  sort(a + 1, a + 1 + n); // 按权值递增排序
  rep(i, 1, n) {
    l[i] = i - 1; // 对排序后的数据构造链表
    r[i] = i + 1;
    p[a[i].second] = i; // 记录排序前的下标对应的排序后的下标
  }
  a[0].first = a[n + 1].first = LLONG_MAX; // 边界
  for (int i = n; i > 1; --i) { // 按输入顺序从后往前计算答案
    int j = p[i]; // j 表示第 i 个输入的数排序后在链表中的位置(下标)
    int left = l[j], right = r[j]; // 当前数在链表中的前驱节点和后继节点的下标
    int v = a[j].first; // 当前节点的权值
    int lv = abs(a[left].first - v); // 与左边节点的差的绝对值
    int rv = abs(a[right].first - v); // 与右边节点的差的绝对值
    if (lv <= rv) { // 如果当前数与 左边的数的差值 小于 与右边的数的插值 按照题目要求选择左边的数
      res[i] = { lv,a[left].second };
      // a[left].second 表示左边的数在原数组中的下标
    }
    else { // 否则选择右边的点
      res[i] = { rv,a[right].second };
    }
    // 将当前节点从链表中删除
    l[right] = left;
    r[left] = right;
  }
  // 按输入顺序输出答案
  rep(i, 2, n) {
    printf("%lld %lld\n", res[i].first, res[i].second);
  }
}
signed main() {
  // int t; cin >> t;
  // while (t--)
    solve();
  return 0;
}


目录
相关文章
|
4月前
|
算法 程序员
【算法训练-链表 六】【链表查找】:链表中倒数第k个节点
【算法训练-链表 六】【链表查找】:链表中倒数第k个节点
24 0
|
6月前
【Leetcode -19.删除链表的倒数第N个结点 -24.两两交换链表中的节点】
【Leetcode -19.删除链表的倒数第N个结点 -24.两两交换链表中的节点】
28 0
|
6月前
|
索引
【链表OJ】相交链表 环形链表1
【链表OJ】相交链表 环形链表1
|
5月前
|
索引
LeetCode题:83删除排序链表中的重复元素 141环形链表
LeetCode题:83删除排序链表中的重复元素 141环形链表
27 0
LeetCode题:83删除排序链表中的重复元素 141环形链表
|
6月前
|
存储
【链表OJ】链表中倒数第k个结点 合并两个链表(含哨兵位) 分割链表 链表的回文结构
【链表OJ】链表中倒数第k个结点 合并两个链表(含哨兵位) 分割链表 链表的回文结构
|
8月前
|
存储
利用快慢指针,求链表的中间结点,判断链表是否是环形链表
利用快慢指针,求链表的中间结点,判断链表是否是环形链表
34 0
|
9月前
链表的遍历
链表的遍历
|
10月前
|
算法 C语言
链表中的倒数第k个结点 合并两个链表 分割链表 链表的回文结构
链表中的倒数第k个结点 合并两个链表 分割链表 链表的回文结构
60 0
|
10月前
|
算法 索引
【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表
【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表
63 0

热门文章

最新文章