这是一道中等难度的题
题目来自:https://www.acwing.com/problem/content/description/138/
题目
给定一个长度为 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| 和 Pi 的值。
数据范围
n ≤ 10^5, |Ai| ≤ 10^9
输入样例:
3
1 5 3
输出样例:
4 1
2 1

解题思路
值得注意的是:
-
解法中需要多次删除序列中的数,所以我们应该使用链表来存储排序序列。
-
题目要求输出差值最小的数的位置,所以我们还需要记录每个数的初始位置。
1 3 5 2 4
为例:
代码实现
package iyushu;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int[] nums = new int[n + 1];
//存放下标,
Integer[] rank = new Integer[n + 1];
for (int i = 1; i <= n; i++) {
nums[i] = input.nextInt();
rank[i] = i;
}
Arrays.sort(rank, 1, n + 1, Comparator.comparingInt(r -> nums[r]));
ListNode protect = new ListNode(0, 0);
ListNode[] nodes = new ListNode[n + 1];
ListNode latestNode = protect;
for (int i = 1; i <= n; i++) {
int index = rank[i];
int num = nums[index];
ListNode node = new ListNode(num, index);
node.pre = latestNode;
latestNode.next = node;
nodes[index] = node;
latestNode = node;
}
// 删除保护节点
protect.next.pre = null;
int[][] ans = new int[n + 1][2];
//倒叙计算结果
for(int i = n; i >= 2; i--){
ListNode node = nodes[i];
ans[i] = calMin(node);
//删掉当前节点
deleteCurNode(node);
}
for (int i = 2; i <= n; i++) {
System.out.println(ans[i][0] + " " + ans[i][1]);
}
}
private static void deleteCurNode(ListNode node) {
if(node.pre != null){
node.pre.next = node.next;
}
if(node.next != null){
node.next.pre = node.pre;
}
}
// 返回一个数组min,min[0]=|Ai−Aj|,min[1] = Pi
static int[] calMin(ListNode node){
int[] min = new int[2];
ListNode pre = node.pre;
if(pre != null){
min[0] = Math.abs(node.num - pre.num);
min[1] = pre.index;
}
ListNode next = node.next;
if(next != null){
int diff = Math.abs(node.num - next.num);
if(pre == null || diff < min[0] || diff == min[0] && next.num < pre.num){
min[0] = diff;
min[1] = next.index;
}
}
return min;
}
static class ListNode{
private int num;
private int index;
private ListNode next;
private ListNode pre;
public ListNode(int num, int index) {
this.num = num;
this.index = index;
}
public ListNode getNext() {
return next;
}
public void setNext(ListNode next) {
this.next = next;
}
public ListNode getPre() {
return pre;
}
public void setPre(ListNode pre) {
this.pre = pre;
}
}
}

复杂度分析
时间复杂度 O(N * logN):算法中所有的循环时间复杂度均为O(N),而数组排序的时间复杂度是O(N * logN),所以总的来说时间复杂度为O(N * logN)。
空间复杂度O(N):算法中所有存储变量空间复杂度都是O(N)。
原文始发于微信公众号(i余数):【算法题解】9. 邻值查找
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/194039.html