华为OD E卷(100分)25-整数对最小和

前言

工作了十几年,从普通的研发工程师一路成长为研发经理、研发总监。临近40岁,本想辞职后换一个相对稳定的工作环境一直干到老, 没想到离职后三个多月了还没找到工作,愁肠百结。为了让自己有点事情做,也算提高一下自己的编程能力,无聊之余打算用一些大厂的编程题练练手。希望通过这些分享能够帮到一些人,也希望能和看到此文的大神们沟通交流,提升自己,更希望在此期间能够找到一份理想的工作。

题目描述

给定两个整数数组array1、array2,数组元素按升序排列。

假设从array1、array2中分别取出一个元素可构成一对元素,现在需要取出k对元素,并对取出的所有元素求和,计算和的最小值。

注意:

两对元素如果对应于array1、array2中的两个下标均相同,则视为同一对元素。

输入

输入两行数组array1、array2,每行首个数字为数组大小size(0 < size <= 100);

0 < array1[i] <= 1000

0 < array2[i] <= 1000

接下来一行为正整数k

0 < k <= array1.size() * array2.size()

输出

满足要求的最小和。

示例

输入

3 1 1 2

3 1 2 3

2

输出

4

说明

用例中,需要取2对元素

取第一个数组第0个元素与第二个数组第0个元素组成1对元素[1,1];

取第一个数组第1个元素与第二个数组第0个元素组成1对元素[1,1];

求和为1+1+1+1=4,为满足要求的最小和。

解题思路

1、暴力枚举法:

  • 双重循环遍历array1和array2的所有元素对,记录它们的和。
  • 将所有可能的和排序,取前K个和的最小值。
  • 但这种方法的时间复杂度较高,为O(n^2 log(n^2)),其中n为数组的大小。

2、最小堆优化:

  • 初始时,将array1的第一个元素与array2的所有元素配对,并将这些配对的和以及对应的array1和array2的下标插入最小堆中。
  • 每次从堆中取出和最小的元素对,将其和加入答案中,并将该元素对对应的array1的下一个元素与array2的当前元素(或下一个未使用的元素)组合并插入堆中。
  • 重复上述步骤,直到从堆中取出了K个元素对。
  • 这种方法的时间复杂度较低,为O(k log n),其中n为数组的大小,且空间复杂度也相对较低。

题解

Java实现

java 复制代码
package huawei.e100;

import java.util.PriorityQueue;
import java.util.Scanner;

/**
* @author arnold
* @date 2024年12月17日
* 
*/
public class T25 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()) {
			//array1
	        int m = sc.nextInt();
	        int[] array1 = new int[m];
	        for (int i = 0; i < m; i++) {
	            array1[i] = sc.nextInt();
	        }
	        // array2
	        int n = sc.nextInt();
	        int[] array2 = new int[n];
	        for (int i = 0; i < n; i++) {
	            array2[i] = sc.nextInt();
	        }

	        // 读取k
	        int k = sc.nextInt();
	        
	        int sum = run(array1, array2, k);
	        System.out.println(sum);
	        
		}

	}
	
	//暴力枚举法
	static int run(int[] array1, int[] array2, int k) {
		PriorityQueue<Integer> data = new PriorityQueue<>((a,b) -> a-b);
		for (int i = 0; i < array1.length && i < k; i++) {
			for (int j = 0; j < array2.length && j < k; j++) {
				data.add(array1[i] + array2[j]);
			}
		}
		int sum = 0;
		while(k > 0) {
			sum += data.poll();
			k--;
		}
		return sum;
	}
	
	// 最小堆化方法
	public static int run2(int[] array1, int[] array2, int k) {
        PriorityQueue<int[]> queue = new PriorityQueue<>((a, b) -> a[0] - b[0]);

        // 初始化最小堆,将array1的第一个元素与array2的所有元素配对并插入堆中
        for (int j = 0; j < array2.length && j < k; j++) {
        	queue.offer(new int[]{array1[0] + array2[j], 0, j});
        }

        int sum = 0;
        while (k > 0) {
            int[] pair = queue.poll();
            assert pair != null;
            sum += pair[0];
            int i = pair[1];
            int j = pair[2];

            // 如果array1还有剩余元素,则将下一个元素与array2的当前元素配对并插入堆中
            if (i + 1 < array1.length) {
            	queue.offer(new int[]{array1[i + 1] + array2[j], i + 1, j});
            }

            k--;
        }

        return sum;
    }

}
相关推荐
MZWeiei1 小时前
PTA:运用顺序表实现多项式相加
算法
GISer_Jing1 小时前
Javascript排序算法(冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序)详解
javascript·算法·排序算法
cookies_s_s1 小时前
Linux--进程(进程虚拟地址空间、页表、进程控制、实现简易shell)
linux·运维·服务器·数据结构·c++·算法·哈希算法
不想编程小谭2 小时前
力扣LeetCode: 2506 统计相似字符串对的数目
c++·算法·leetcode
水蓝烟雨2 小时前
[HOT 100] 2187. 完成旅途的最少时间
算法·hot 100
菜鸟一枚在这3 小时前
深度解析建造者模式:复杂对象构建的优雅之道
java·开发语言·算法
gyeolhada4 小时前
2025蓝桥杯JAVA编程题练习Day5
java·数据结构·算法·蓝桥杯
阿巴~阿巴~4 小时前
多源 BFS 算法详解:从原理到实现,高效解决多源最短路问题
开发语言·数据结构·c++·算法·宽度优先
给bug两拳4 小时前
Day9 25/2/22 SAT
算法
_Itachi__4 小时前
LeetCode 热题 100 73. 矩阵置零
算法·leetcode·矩阵