一个数组中两个数的和为N,找出这两个数字的下标

本文介绍了一种使用Java实现的高效算法,该算法用于在一个整数数组中寻找两个数,使它们的和等于特定的目标值。通过对数组进行排序并利用双指针技巧,可以在O(n log n)的时间复杂度内解决问题。

因为最近用的是java就按java写了。

话说最近才发现原来java面试时候居然可以用库里的函数。

分析,两个数字的和为N。那么这两个数字是否是唯一的呢?输出的下标是否是第一对出现的呢?

1,我们假设这两个数字是唯一的

和是唯一的,那么其中一个数字越大,另一个数字就越小。想到大小关系,我们就想到了排序。那么首先排序:

int array[]={ 1, 2, 7, 9, 13, 57, 36, 26, 55, 11, 9, 6, 3, 89, 36, 75, 36, 76, 95, 98, 101, 320, 520, 85, 36, 62, 49, 96, 1 };

因为要返回原始下标,所以要进行记录

int array1[]=array.clone();//这种记录最完善,但是查询不方便
 Map<Integer,Integer> hs=new HashMap<Integer,Integer>();//这种方法没有顺序性只能查到原始下标但不能确定顺序,查询方便

Arrays.sort(array); 平均时间复杂度o(nlogn)

然后最小的加上最大的,如果大于n,证明大的太大了,就尝试第二大的数字。如果小于n就证明小的太小了,就尝试第二小的数字。
代码如下:

 while((addAns=array[i]+array[j]-N)!=0&&i<j){
         if(addAns>0){
         j--;
         }else{
         i++;
         }
        }
        if(i==j){
         System.out.println("没有结果");
         return;
        }

这样array[i]和array[j]就是所求的两个数字。

再通过hs.get(array[i]) 和hs.get(array[j])就得到了这两个数字的原始下标输出即可。但由于缺乏顺序性,这两个下标可能不是第一个出现的。
通过遍历数组的方式可以找到第一组数字。


完整代码:

int array[]={ 1, 2, 7, 9, 13, 57, 36, 26, 55, 11, 9, 6, 3, 89, 36, 75, 36, 76, 95, 98, 101, 320, 520, 85, 36, 62, 49, 96, 1 };
    int array1[]=array.clone();
    Map<Integer,Integer> hs=new HashMap<Integer,Integer>();
    for (int i = 0; i < array.length; i++) {
        hs.put(array[i], i);
}
        
        Arrays.sort(array);
        for (int i = 0; i < array.length; i++) {
        System.out.print(array[i]+",");
}
        System.out.println();
   
        for (int i = 0; i < array.length; i++) {
        System.out.print(array1[i]+",");
}
        System.out.println();
        
   
        int N = 35,s1=-1,s2=-1,i=0,j=array.length-1;
        int addAns;
        //比较,如果addAns>0表示 时间复杂度o(n)
        while((addAns=array[i]+array[j]-N)!=0&&i<j){
        if(addAns>0){
        j--;
        }else{
        i++;
        }
        }
        if(i==j){
        System.out.println("没有结果");
        return;
        }
        //找到其中一组下标
        System.out.println("any one: "+hs.get(array[i]) + ":" + array[i] + "+" + hs.get(array[j]) + ":" + array[j]);
        //找到第一组下标 时间复杂度o(n)
        for(int k=0;k<array1.length-1;k++){
        if(array1[k]==array[i]&&s1<0){
        s1=k;
        }
        if(array1[k]==array[j]&&s2<0){
        s2=k;
        }
        if(s1>=0&&s2>=0)
        {
        break;
        }
        }
        System.out.println("first one: "+s1 + ":" + array[i] + "+" + s2 + ":" + array[j]);

<think>我们有一个问题:在数组找出两个数,使它们的等于目标值,并返回这两个数的下标(从1开始计数)。 根据引用[1][2][3][4],我们可以总结出几种方法: 1. 暴力法:双重循环遍历所有可能的组合,时间复杂度为$O(n^2)$,空间复杂度$O(1)$。 2. 哈希表法:使用一个哈希表(字典)存储遍历过的元素及其下标。对于每个元素,计算目标值与当前元素的差值,检查差值是否在哈希表中。如果在,则返回两个下标。时间复杂度$O(n)$,空间复杂度$O(n)$。 注意:题目要求下标从1开始,并且假设数组中只存在唯一解。 我们选择效率更高的哈希表法来实现。 步骤: 1. 创建一个空字典(哈希表)用于存储元素值到索引的映射(注意:题目要求下标从1开始,但程序内部通常从0开始,最后加1即可)。 2. 遍历数组,对于每个元素`num`,计算`diff = target - num`。 3. 检查`diff`是否在字典中: - 如果在,则返回`[字典中存储的索引+1, 当前索引+1]`(因为题目要求下标从1开始,并且要保证第一个下标小于第二个下标)。 - 如果不在,则将当前元素及其索引(从0开始)存入字典。 注意:由于题目要求第一个下标小于第二个下标,且我们遍历的顺序是从前往后,所以当找到时,字典中存储的索引一定小于当前索引。 实现代码(Python):</think>### 之和问题算法实现 在数组找出两个之和等于目标值的算法是经典问题(Two Sum),主要有种实现方法: #### 1. 暴力枚举法 - **时间复杂度**:$O(n^2)$ - **空间复杂度**:$O(1)$ - **原理**:双重循环遍历所有可能的组合 - **代码实现**: ```python def twoSum(nums, target): for i in range(len(nums)): for j in range(i + 1, len(nums)): if nums[i] + nums[j] == target: return [i + 1, j + 1] # 下标从1开始 ``` > 优点:实现简单,无需额外空间 > 缺点:数据量大时效率低(如$n=10^4$需计算$5 \times 10^7$次)[^4] #### 2. 哈希表优化法 - **时间复杂度**:$O(n)$ - **空间复杂度**:$O(n)$ - **原理**:用哈希表存储遍历过的元素值及其索引 - **代码实现**: ```python def twoSum(nums, target): hashtable = {} for idx, num in enumerate(nums): diff = target - num if diff in hashtable: return [hashtable[diff] + 1, idx + 1] # 下标从1开始 hashtable[num] = idx # 存储当前值及索引 ``` > 优点:线性时间复杂度,适合大数据量 > 缺点:需要额外空间存储哈希表[^2][^3] #### 关键特性 1. **下标处理**:返回下标需从1开始计数(内部索引+1) 2. **唯一解假设**:题目保证有且仅有一组解 3. **边界条件**:空数组直接返回;相同元素需区分索引(哈希表会覆盖旧值但不影响解的唯一性) #### 示例验证 ```python nums = [20, 70, 110, 150] target = 90 print(twoSum(nums, target)) # 输出 [1, 2] (20+70=90) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值