事件推送问题

一、题目描述

同一个数轴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]);
            }
        }
    }
}
相关推荐
Jerry8 分钟前
LeetCode 28. 找出字符串中第一个匹配项的下标
算法
Jerry2 小时前
LeetCode 459. 重复的子字符串
算法
闲猫4 小时前
Spring AI 对接Deepseek ChatModel 聊天对话
java·前端·spring
海石5 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石5 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
自信的未来6 小时前
JSON 工具|Web Worker 工程化打包 + 语法自动修复 + 多语言代码生成实战
java·前端·json
Brookty6 小时前
【JavaEE】线程安全(一).4:写块串行保安全、CAS
java·开发语言·java-ee·多线程·线程安全
我叫黑大帅6 小时前
MySQL 并发插入竞态问题:原子写入实践指南
后端·mysql·面试
Jerry7 小时前
LeetCode 151. 反转字符串中的单词
算法