华为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;
    }

}
相关推荐
BUG收容所所长1 分钟前
二分查找的「左右为难」:如何优雅地找到数组中元素的首尾位置
前端·javascript·算法
itsuifengerxing39 分钟前
python 自定义无符号右移
算法
猎板PCB厚铜专家大族1 小时前
高频 PCB 技术发展趋势与应用解析
人工智能·算法·设计规范
dying_man1 小时前
LeetCode--24.两两交换链表中的结点
算法·leetcode
yours_Gabriel1 小时前
【力扣】2434.使用机器人打印字典序最小的字符串
算法·leetcode·贪心算法
草莓熊Lotso2 小时前
【数据结构初阶】--算法复杂度的深度解析
c语言·开发语言·数据结构·经验分享·笔记·其他·算法
KyollBM2 小时前
【CF】Day75——CF (Div. 2) B (数学 + 贪心) + CF 882 (Div. 2) C (01Trie | 区间最大异或和)
c语言·c++·算法
CV点灯大师2 小时前
C++算法训练营 Day10 栈与队列(1)
c++·redis·算法
GGBondlctrl3 小时前
【leetcode】递归,回溯思想 + 巧妙解法-解决“N皇后”,以及“解数独”题目
算法·leetcode·n皇后·有效的数独·解数独·映射思想·数学思想
武子康3 小时前
大数据-276 Spark MLib - 基础介绍 机器学习算法 Bagging和Boosting区别 GBDT梯度提升树
大数据·人工智能·算法·机器学习·语言模型·spark-ml·boosting