【算法题解】9. 邻值查找

news2024/12/30 3:34:44

文章目录

    • 题目
    • 解题思路
    • 代码实现
    • 复杂度分析

这是一道中等难度的题。
题目来自:AcWing

题目

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

对于 A 中的每一个数 Ai,求:
min|Ai−Aj|,其中 1 <= j < i

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

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

输出格式
输出共 n−1 行,每行输出两个整数,数值之间用空格隔开。
分别表示当 i2∼n 时,对应的 min|Ai−Aj|Pi 的值。

数据范围
n <= 10^5
|Ai| <=10^9

输入样例:

3
1 5 3

输出样例:

4 1
2 1

解题思路

首先排除暴力解法,毫无疑问会超时。如果不暴力循环,那么怎么可以获取到位置在 Ai 前面且与 Ai 差值最小的数呢?

既然是求差值最小,那么有一个思路就是可以将序列中的所有数按照从小到大排序,那么与Ai差值最小的数肯定就是排序后Ai的前一后数或者后一个数。但是按正常从前往后找的时候,我们无法确定这两个数排序前是否是在 Ai 的前面。

这时候可以考虑倒序去找,即先找最后一个 An 的答案,因为对于最后一个数来说,其他数肯定都在它的前面。当得到最后一个数的答案后,直接将 An 从排序后的序列中删除,然后再求 A(n-1) 的答案,这个时候序列中的其它数排序前肯定都在A(n-1)前面,因为在它后面的数都已经被删掉了,以此类推,直到得到 A2 的答案。

值得注意的是:

  1. 解法中需要多次删除序列中的数,所以我们应该使用链表来存储排序序列。
  2. 题目要求输出差值最小的数的位置,所以我们还需要记录每个数的初始位置。

以输入 1 3 5 2 4 为例:
【算法题解】9. 邻值查找

代码实现

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 ∗ l o g N ) O(N * logN) O(NlogN):算法中所有的循环时间复杂度均为 O ( N ) O(N) O(N),而数组排序的时间复杂度是 O ( N ∗ l o g N ) O(N * logN) O(NlogN),所以总的来说时间复杂度为 O ( N ∗ l o g N ) O(N * logN) O(NlogN)

空间复杂度 O ( N ) O(N) O(N):算法中所有存储变量空间复杂度都是 O ( N ) O(N) O(N)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/160785.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

10行代码带你轻松抓取博客清单

一、前言 今天在网上偶遇一款html解析利器HtmlAgilityPack&#xff0c;免费下载地址&#xff1a;入口。 HtmlAgilityPack是.net下的一个HTML解析类库&#xff0c;支持用XPath来解析HTML。通过该类库&#xff0c;先通过浏览器获取到xpath获取到节点内容然后再通过正则表达式匹…

【operator bool】while(cin >> str)是什么意思?

文章目录一、前言二、cin是什么&#xff1f;三、隐式类型转化如何发生&#xff1f;一、前言 在oj题中&#xff0c;为了实现多行输入&#xff0c;我们经常可以看到这样的写法&#xff1a;while(cin >> str)&#xff0c;这究竟是什么意思呢&#xff1f;为了理解其中的含义&…

c++ 可变参数的三种实现方式

c 可变参数 方法一&#xff1a; C语言的: va_list1 #include <stdio.h> #include <stdarg.h>int add_nums(int count, ...) {int result 0;va_list args;va_start(args, count); // C23 起能省略 countfor (int i 0; i < count; i) {result va_arg(args, i…

bresenham algorithm

#! https://zhuanlan.zhihu.com/p/598780689 bresenham algorithm 全象限区域bresenham algorithm计算的python/c实现 bresenham algorithm为计算机图形学中使用像素点显示直线的算法&#xff0c;算法使用整数运算&#xff0c;能大幅提升计算速度。最近概率栅格建图算法中涉及…

CloudCanal实战-Oracle数据迁移同步到PostgreSQL

简述 本篇文章主要介绍如何使用 CloudCanal 构建一条 Oracle 到 PostgreSQL 的数据同步链路 技术要点 缩小的数据库权限要求 CloudCanal 对 Oracle 数据库的高权限要求&#xff0c;主要来自两个面向 DBA 的操作&#xff0c;自动构建字典和 自动切换归档日志&#xff0c;这两…

详解 strtok 函数以及模拟实现

目录 一、strtok 函数的介绍 二、strtok 函数的模拟实现 一、strtok 函数的介绍 函数原型&#xff1a; char* strtok(char* str, const char* delimiters); delimiter n.[计]分隔符&#xff0c;定界符&#xff08;a character that marks the beginning or end of a unit o…

KMP算法详解+动图演示

目录 一、KMP算法简介 二、KMP算法的详细图解 1. 先了解BF算法的基本思路 2. 简单了解KMP算法 3. next数组的引入 4. next数组的代码实现&#xff08;含动态演示&#xff09; 三、KMP算法完整代码 一、KMP算法简介 KMP算法是一种改进的字符串匹配算法&#xff0c;由 …

【算法】二分图判定

目录1.概述2.代码实现3.应用本文参考&#xff1a; LABULADONG 的算法网站 1.概述 &#xff08;1&#xff09;二分图 (Bipartite Graph)&#xff0c;又称为二部图&#xff0c;是图论中的一种特殊模型。 设 G (V, E) 是一个无向图&#xff0c;如果顶点 V 可分割为两个互不相交的…

Unity 和vs2022对接问题

第一个问题&#xff1a;在vs中编写好的程序在unity中预览出现乱码&#xff1b;提示&#xff1a;只要是乱码的问题90%离不开编码表Unity中的编码表是utf-8,而vs中默认的应该是GB2312。英文还好&#xff0c;中文可定就会出现乱码&#xff0c;解决方法也很简单&#xff1a;把vs中的…

【Python基础四】入门级朋友看的超详教程

前言 这是最后一篇基础的文章啦 往期文章&#xff1a; 【Python基础一】入门级朋友看的超详教程 【Python基础二】入门级朋友看的超详教程 【Python基础三】入门级朋友看的超详教程 刚开始接触Python的宝子&#xff0c;有什么不懂的都可以私信我哦 我还准备了大量的免费…

目标检测:YOLO V2思路解读

目标检测&#xff1a;YOLO V2思路解读YOLO V1存在的问题主要改进Batch NormalizationHigh Resolution ClassifierConvolutional With Anchor BoxesDimension ClusterDirect location PredictionFine-Grained FeaturesMulti-Scale TrainingLoss FunctionYOLO V1存在的问题 对于…

使用Redis代替Session实现短信登陆

1.集群的Session共享问题 多台Tomcat并不共享Session存储空间&#xff0c;当请求切换到不同tomcat服务器时会导致数据丢失&#xff1a; 当用户量增多&#xff0c;我们需要进行负载均衡、对tomcat做水平扩展&#xff0c;可是存储在Tomcat里的Session不是共享的&#xff0c;这…

从C和C++内存管理来谈谈JVM的垃圾回收算法设计-上

从C和C内存管理来谈谈JVM的垃圾回收算法设计-上引言C内存模型malloc堆内存分配过程malloc为什么结合使用brk和mmapmalloc如何通过内存池管理Heap区域垃圾收集器引言 本文想和大家来探讨一下JVM是如何对堆内存进行管理和垃圾回收,相关书籍如深入理解JVM第三版中已经介绍过了相关…

OSCP-Vulnhub靶机记录-digitalworldlocal-fall

Vulnhub靶机记录-digitalworldlocal-fall靶机描述安装扫描枚举使用kali自带的FUZZ权限提升靶机描述 靶机地址&#xff1a;https://www.vulnhub.com/entry/digitalworldlocal-fall,726/ Description To celebrate the fifth year that the author has survived his infosec ca…

也来聊聊滑块验证码的那些事

单位做攻防演习&#xff0c;我扮演攻击方尝试破解。发现滑块验证码做了升级&#xff0c;比之前复杂了很多。好在仍然是一维验证&#xff0c;不用太麻烦。https接口里读出的是json对象&#xff0c;先从对象里取出图片转的base64编码&#xff0c;然后把字符串转回成numpy.ndarray…

Verilog HDL 基础语法

一、逻辑值 0: 逻辑低电平&#xff0c;条件为假 1: 逻辑高电平&#xff0c;条件为真 z: 高阻态&#xff0c;无驱动 x: 未知逻辑电平二、实际例子 1. 模块名一般与文件名相同 线网型变量会被映射成一条真实存在的物理连线。 寄存器型变量会被映射成一个寄存器。 2. 参数 para…

2、JavaScript快速入门

2.1 引入JavaScript 内部标签 <!-- 在script标签内写JavaScript(简称js)代码&#xff0c;代码块可以放在head中&#xff0c;也可以放在body中--> <script>// alert:弹窗alert(Hello,world!); //注意以分号结尾 </script>外部引入 hello.js alert(Hello,worl…

分享120个ASP源码,总有一款适合您

ASP源码 分享120个ASP源码&#xff0c;总有一款适合您 链接&#xff1a;https://pan.baidu.com/s/1WwTsUTLS_qLvP-TC1w-1vQ?pwdvxpk 提取码&#xff1a;vxpk 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c;大家下载…

OB0207 obsidian 自动获取url链接:auto-link-title插件使用

序号解读&#xff1a; 01——软件基础使用、基础语法 02——插件使用 03——综合实战 0 写在前面 Ob社区插件汇总&#xff1a;Airtable - OB社区插件汇总 - Johnny整理 - 每周更新 - B站 Johnny学Explore the "OB社区插件汇总 - Johnny整理 - 每周更新 - B站 Johnny学&qu…

过去一年渲染了3亿帧,助力了63.81亿票房、1150亿播放量丨瑞云渲染年度大事记

2022年&#xff0c;注定是充满未知和挑战的一年。抗疫三年&#xff0c;终于在2022年底迎来放开&#xff0c;我们怀着忐忑的心情告别了核酸、行程码和封控&#xff0c;成为了自己健康的第一负责人。这段时间大家应该都忙着和病毒做斗争吧&#xff0c;瑞云各个岗位的小伙伴们也都…