事件推送问题

一、题目描述

同一个数轴X上有两个点的集合A={A1, A2, ..., Am}和B={B1, B2, ..., Bn},Ai和Bj均为正整数,A、B已经按照从小到大排好序,A、B均不为空,给定一个距离R(正整数),列出同时满足如下条件的所有(Ai, Bj)数对:Ai <= Bj Ai, Bj之间的距离小于等于R 在满足1,2的情况下,每个Ai只需输出距离最近的Bj 输出结果按Ai从小到大的顺序排序。

二、输入输出描述

输入描述

  • 第一行三个正整数m,n,R
  • 第二行m个正整数,表示集合A
  • 第三行n个正整数,表示集合B

输入限制:1<=R<=100000, 1<=n,m<=100000, 1<=Ai,Bj<=1000000000

输出描述

  • 每组数对输出一行Ai和Bj,以空格隔开

三、示例

|----|---------------------------|
| 输入 | 4 5 5 1 5 5 10 1 3 8 8 20 |
| 输出 | 1 1 5 8 5 8 |
| 说明 | |

四、解题思路

  1. 核心思想

通过 "排序 + 双指针" 实现高效的元素匹配:先对setB排序,再用单向移动的指针遍历setB,为setA的每个元素找到满足 "≥valueA 且差值≤r" 的最小setB元素 ------ 核心是 "排序降维复杂度 + 双指针避免重复遍历"。

  1. 问题本质分析
  • 表层问题:在两个数组中匹配满足 "B 元素≥A 元素且差值≤r" 的元素对,每个 A 元素匹配最小的符合条件的 B 元素;
  • 深层问题:
    1. 无序数组的高效匹配:若setB无序,需对每个 A 元素遍历整个 B(时间复杂度 O (m*n)),排序后可通过双指针将复杂度降至 O (m + n log n);
    2. 单向指针的合理性:因setB升序、setA遍历无顺序要求,指针仅需正向移动(已跳过的 B 元素均 < A 当前元素,无需回头)。
  1. 核心逻辑
  • 排序预处理:对setB升序排序,保证元素有序,为双指针单向移动提供基础;
  • 双指针单向遍历:indexB仅正向移动,避免对setB的重复遍历,降低时间开销;
  • 条件筛选:先找到setB中≥valueA 的最小元素,再校验差值是否≤r,保证匹配的是 "最小且符合误差的 B 元素"。
  1. 步骤拆解

  2. 输入读取与初始化

    • 读取setA长度、setB长度、误差范围r
    • 读取setAsetB的所有元素。
  3. 预处理(排序)

    • setB进行升序排序,为双指针匹配做准备。
  4. 双指针匹配

    • 初始化indexB=0(指向setB的起始位置);
    • 遍历setA的每个元素valueA
      1. 移动indexB,直到setB[indexB] ≥ valueA(或indexB越界);
      2. 若未越界且差值≤r,输出元素对;否则跳过。
  5. 结果输出

    • 逐行输出满足条件的元素对,无满足条件的则无输出。

五、代码实现

java 复制代码
import java.util.Arrays;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 读取 m、n、r
        int m = sc.nextInt();
        int n = sc.nextInt();
        int r = sc.nextInt();
        int[] setA = new int[m];
        int[] setB = new int[n];
        // 读取数组 A
        for (int x = 0; x < m; x++) {
            setA[x] = sc.nextInt();
        }
        // 读取数组 B
        for (int y = 0; y < n; y++) {
            setB[y] = sc.nextInt();
        }
        // 调用匹配函数
        matchPairs(setA, setB, r);
    }
    public static void matchPairs(int[] setA, int[] setB, int range) {
        Arrays.sort(setB); // 先对 B 进行排序,确保双指针法可行
        int indexB = 0; // 指向 B 中当前检查的元素
        // 遍历数组 A 中的每个元素
        for (int valueA : setA) {
            // 移动 indexB,使其指向 >= valueA 的最小元素
            while (indexB < setB.length && setB[indexB] < valueA) {
                indexB++;
            }
            // 检查是否满足误差范围
            if (indexB < setB.length && setB[indexB] - valueA <= range) {
                System.out.println(valueA + " " + setB[indexB]);
            }
        }
    }
}
相关推荐
明洞日记8 小时前
【设计模式手册018】访问者模式 - 分离数据结构与操作
数据结构·设计模式·访问者模式
夏鹏今天学习了吗8 小时前
【LeetCode热题100(76/100)】划分字母区间
算法·leetcode·职场和发展
没有bug.的程序员8 小时前
SOA、微服务、分布式系统的区别与联系
java·jvm·微服务·架构·wpf·日志·gc
LYFlied8 小时前
【每日算法】LeetCode 560. 和为 K 的子数组
前端·数据结构·算法·leetcode·职场和发展
素雪风华8 小时前
只使用Docker+Maven实现全自动化流程部署服务;Docker创建ffmpeg环境;
java·运维·后端·docker·容器·自动化·maven
梦里不知身是客118 小时前
explain分析SQL语句分析sql语句的优劣
java·数据库·sql
你想考研啊8 小时前
k8s使用kubectl报错
java·docker·kubernetes
Epiphany.5568 小时前
dfn序优化树上背包
算法
fei_sun8 小时前
【数据结构】败者树、B树、排序、查找
数据结构·b树