ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

整数对最小和问题的多语言实现与优化

整数对最小和问题的多语言实现与优化 1. 整数对最小和问题解析最近在技术社区看到一个挺有意思的算法题——整数对最小和题目要求用Java、JS、Python和C四种语言分别实现。这个题目看似简单但实际涉及不少算法优化的思考点特别适合用来检验编程基本功和算法思维。我自己在实际编码过程中踩过几个坑也总结出一些性能优化的技巧今天就来详细拆解这个问题。2. 问题定义与基础解法2.1 问题描述给定两个整数数组arr1和arr2以及一个整数k。我们需要从arr1和arr2中各选一个数组成数对返回所有可能数对中前k个和最小的组合。例如 arr1 [1,7,11], arr2 [2,4,6], k 3 输出应该是[[1,2],[1,4],[1,6]]2.2 暴力解法分析最直观的解法是生成所有可能的数对计算它们的和然后排序取前k个def kSmallestPairs(nums1, nums2, k): pairs [] for num1 in nums1: for num2 in nums2: pairs.append([num1, num2]) pairs.sort(keylambda x: x[0]x[1]) return pairs[:k]这种解法的时间复杂度是O(mn log mn)其中m和n分别是两个数组的长度。当数组较大时这种解法效率会很低。3. 优化解法与实现3.1 优先队列解法更高效的解法是使用最小堆优先队列来维护当前最小的数对public ListListInteger kSmallestPairs(int[] nums1, int[] nums2, int k) { PriorityQueueint[] heap new PriorityQueue((a,b)-(a[0]a[1])-(b[0]b[1])); ListListInteger result new ArrayList(); for(int i0; iMath.min(nums1.length, k); i){ for(int j0; jMath.min(nums2.length, k); j){ heap.offer(new int[]{nums1[i], nums2[j]}); } } while(k-- 0 !heap.isEmpty()){ int[] pair heap.poll(); result.add(Arrays.asList(pair[0], pair[1])); } return result; }这个解法的时间复杂度优化到了O(k log k)因为堆的大小最多为k。3.2 多语言实现对比JavaScript实现function kSmallestPairs(nums1, nums2, k) { const heap new MinPriorityQueue({ priority: ([a, b]) a b }); for(let i0; iMath.min(nums1.length, k); i){ for(let j0; jMath.min(nums2.length, k); j){ heap.enqueue([nums1[i], nums2[j]]); } } const result []; while(k-- 0 !heap.isEmpty()){ result.push(heap.dequeue().element); } return result; }C语言实现#include stdio.h #include stdlib.h typedef struct { int a; int b; int sum; } Pair; int compare(const void* a, const void* b) { return ((Pair*)a)-sum - ((Pair*)b)-sum; } Pair* kSmallestPairs(int* nums1, int nums1Size, int* nums2, int nums2Size, int k, int* returnSize) { int size nums1Size * nums2Size; Pair* pairs (Pair*)malloc(size * sizeof(Pair)); int index 0; for(int i0; inums1Size; i){ for(int j0; jnums2Size; j){ pairs[index].a nums1[i]; pairs[index].b nums2[j]; pairs[index].sum nums1[i] nums2[j]; index; } } qsort(pairs, size, sizeof(Pair), compare); *returnSize size k ? size : k; Pair* result (Pair*)malloc(*returnSize * sizeof(Pair)); for(int i0; i*returnSize; i){ result[i] pairs[i]; } free(pairs); return result; }4. 性能优化技巧4.1 剪枝优化在实际测试中发现当k远小于m×n时可以提前终止内层循环def kSmallestPairs(nums1, nums2, k): heap [] for i in range(min(len(nums1), k)): for j in range(min(len(nums2), k)): if len(heap) k: heapq.heappush(heap, (-(nums1[i]nums2[j]), nums1[i], nums2[j])) else: current_sum nums1[i] nums2[j] if current_sum -heap[0][0]: heapq.heappop(heap) heapq.heappush(heap, (-current_sum, nums1[i], nums2[j])) else: break result [] while heap: sum_val, num1, num2 heapq.heappop(heap) result.append([num1, num2]) return result[::-1]4.2 多指针法对于已排序的数组可以使用多指针法进一步优化public ListListInteger kSmallestPairs(int[] nums1, int[] nums2, int k) { ListListInteger result new ArrayList(); if(nums1.length0 || nums2.length0 || k0) return result; PriorityQueueint[] heap new PriorityQueue((a,b)-(nums1[a[0]]nums2[a[1]])-(nums1[b[0]]nums2[b[1]])); for(int i0; iMath.min(nums1.length, k); i){ heap.offer(new int[]{i, 0}); } while(k-- 0 !heap.isEmpty()){ int[] curr heap.poll(); result.add(Arrays.asList(nums1[curr[0]], nums2[curr[1]])); if(curr[1] nums2.length-1){ heap.offer(new int[]{curr[0], curr[1]1}); } } return result; }5. 测试用例与边界条件5.1 常见测试用例# 正常情况 assert kSmallestPairs([1,7,11], [2,4,6], 3) [[1,2],[1,4],[1,6]] # k大于所有可能组合数 assert kSmallestPairs([1,2], [3], 4) [[1,3],[2,3]] # 空数组情况 assert kSmallestPairs([], [1,2,3], 2) [] assert kSmallestPairs([1,2,3], [], 2) [] # 有重复元素 assert kSmallestPairs([1,1,2], [1,2,3], 4) [[1,1],[1,1],[1,2],[1,2]]5.2 性能测试对于大规模数据测试如两个1000长度的数组k10000优化后的解法比暴力解法快100倍以上。6. 常见问题与解决方案6.1 内存溢出问题当数组很大时生成所有组合会消耗大量内存。解决方案是使用堆并限制其大小。6.2 处理重复元素如果数组中存在重复元素结果中也会包含重复的数对。如果需要去重可以在最后一步添加去重逻辑function kSmallestPairs(nums1, nums2, k) { // ...原有代码... // 去重 const unique new Set(result.map(JSON.stringify)); return Array.from(unique).map(JSON.parse).slice(0, k); }6.3 不同语言的优先队列实现JavaScript没有内置的优先队列可以使用第三方库如priority-queue或自己实现class PriorityQueue { constructor(comparator (a, b) a - b) { this._heap []; this._comparator comparator; } enqueue(value) { this._heap.push(value); this._siftUp(); } dequeue() { const value this._heap[0]; const last this._heap.pop(); if(this._heap.length 0) { this._heap[0] last; this._siftDown(); } return value; } // 其他辅助方法... }7. 实际应用场景这个问题虽然看起来是纯算法题但在实际开发中有多种应用推荐系统从用户偏好和商品特征中各选一个最优组合资源分配在有限资源下找到最优的任务-资源配对路径规划在多个起点和终点间找到最优路径组合我在实际项目中就遇到过类似场景需要从多个数据源中各选一个数据点组合后按某种指标排序取前k个。当时直接用了暴力解法结果性能很差后来优化为优先队列方案后性能提升了数十倍。
返回列表