java 数组中两两相加等于某个数的组合种数 蛮力解法 排序解法

本文介绍了一种求解数组中两数之和等于特定数值的有效算法。通过蛮力法和排序法两种策略,实现对数组中两两元素求和等于指定数值组合数量的计算。排序法将时间复杂度降低至接近O(logn),显著提高了效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

求数组中两两相加等于某个数的组合中种数
   下面提两种解法:
    1.蛮力算法:时间复杂度为O(n^2)
    2.排序法:
       时间复杂度为O(logn) 对数组先进行排序,定义begin和end分别指向数组的
       第一个元素和最后一个元素,分为以下三种情况:
         1:若array[begin]+array[end]<某个数(number)  则 begin++,即为:begin向后移动一位
         2:若array[begin]+array[end]>某个数(number)  则end--,即为:end向前移动一位
         3:若array[begin]+array[end]=某个数(number)  则begin++,end--;即为:begin向后移动一位,end向前移动一位
package datastruct.usearray;
import java.util.Arrays;
import java.util.Scanner;
public class GetResult20OfTwoEle {
//方法一:蛮力算法
private static void method1(int array[],int number) {
int count=0;//两两相加等于number的组合种数
System.out.println("方法一:");
for (int i = 0; i < array.length-1; i++) {
for (int j = i+1; j < array.length; j++) {
if (array[i]+array[j]==number) {
count++;
System.out.println("第"+count+"种"+": "+array[i]+"+"+array[j]+"=20");
}
}
}
System.out.println("等于20的组合共有"+count+"种");
}
private static void method2(int array[],int number) {
Arrays.sort(array);//对数组进行排序
int begin=0;
int end=array.length-1;
int count=0;//两两相加等于number的组合种数
System.out.println("方法二:");
while (begin!=end) {
if (array[begin]+array[end]<number) {
begin++; //begin向后移动一位
}else if (array[begin]+array[end]>number) {
end--; //end向前移动一位
}else {
count++;
System.out.println("第"+count+"种"+": "+array[begin]+"+"+array[end]+"=20");
begin++;
end--;
}
}
System.out.println("等于20的组合共有"+count+"种");
}
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入元素的个数:");
int n=scanner.nextInt();
System.out.println("请输入求解两个元素相加的数值:");
int number=scanner.nextInt();
System.out.println("输入"+n+"个数组元素:");
int array[]=new int[n];
for (int i = 0; i <n; i++) {
array[i]=scanner.nextInt();
}
method1(array,number);
method2(array,number);
}

运行结果如下:
     
### 问题分析 给定一个长度为 N 的正整序列,我们需要计算所有两两相加的结果,并找出其中前 M 大的和。由于直接生成所有的组合会涉及到 O(N^2) 空间复杂度,因此需要一种更高效的方式来处理这个问题。 #### 解决思路: 1. **暴力解法**(不推荐用于大规模据集) - 直接枚举每一对元素,将结果存入数组或列表中,然后排序出前 M 大。 2. **优先队列 (最大堆)** - 使用最大堆来维护当前找到的最大M个数字,在遍历过程中动态调整堆结构,保证最后得到的就是我们想要的答案之一。 3. **双指针 + 排序** - 对原数组先做一次升序排列;初始化两个指针分别指向首尾两端; 根据头尾之和判断是否应该更新候选集合以及移动哪一侧指针继续搜索更大可能性。 4. **二分查找+计验证** - 设定目标区间 `[left, right]` ,尝试利用二分思想确定最终答案范围内的界限 `mid` ; 检查满足条件的量是否足够填充所需top-m位置即可缩小边界直到收敛至准确点位。 考虑到题目给出的据规模限制(N<=3000),可以采用较为简单的基于堆的方法来做优化,既避免了完全展开全部配对又能够较好地控制时间开销。 以下是Python代码示例实现了上述提到的第一个可行方案——“双指针”算法,该方法的时间复杂度大约是O(nlogn+m): ```python def top_m_sums(nums, m): nums.sort() # 先排序 n = len(nums) result = [] seen = set() left, right = 0, n-1 while len(result)<m and left<right: sum_ = nums[left]+nums[right] if (sum_,left,right) not in seen: heapq.heappush(result,-sum_) seen.add((sum_,left,right)) if len(heapq.nsmallest(m,result)) == m : break max_sum = -(heapq.nsmallest(1,result)[0]) for i in range(left+1,n): tempSum=nums[i]+nums[right] if tempSum>max_sum : if (tempSum,i,right)not in seen: heapq.heappushpop(result,-tempSum) seen.discard((-result[0],i,right)) for j in reversed(range(right)): tempSum=nums[j]+nums[left] if tempSum>max_sum : if(tempSum,left,j) not in seen: heapq.heappushpop(result,-tempSum) seen.discard((-result[0],left,j)) left+=1 right-=1 return sorted([-x for x in result],reverse=True) # 示例输入: numbers=[1,3,5,7,9] k=6 print(top_m_sums(numbers,k)) ``` 注意此段代码并不是最高效的解决方案,它只是一个演示性质的例子,实际应用时可以根据具体情况进一步简化逻辑提高性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值