167. 两数之和 II - 输入有序数组


两数之和 II - 输入有序数组

原题链接:https://leetcode.cn/problems/two-sum-ii-input-array-is-sorted/

题目

在这里插入图片描述

题解

解法一:利用HashMap

题目确保仅存在一个有效答案,非递减序列,不可使用同一个元素。
思路:采用for循环遍历,利用HashMap可以将当前元素的信息进行保存,方便后续查询。key:该数 的值,value:该数对应的下标

  1. 计算 target 减去 当前元素的值,得到需要查询的值 x
  2. 利用HashMap的containKey()方法,查询之前该数是否出现过,如果已出现则该数取对应的value值,return {该数下标,当前元素下标}
  3. 若未出现过,将当前数和对应下标存入HashMap中
class Solution {
   public int[] twoSum(int[] numbers, int target) {
       Map<Integer,Integer> map = new HashMap<>();
       int n = numbers.length;
       map.put(numbers[0], 1);
       for (int i = 1; i < n; i++){
           int x = target - numbers[i];
           if (map.containsKey(x)){
               return new int[] {map.get(x), i+1};
           }
           map.put(numbers[i], i+1);
       }
       return new int[]{};
   }
}

复杂度分析:

  • 时间复杂度:O(n)

解法一利用Map集合的特点,思路简单,但多次调用方法,耗时长

解法二:巧用数组

题目的数据范围和大小都不大,-1000<=numbers[i]<=1000,那两数之和的范围就在-2000<=sum<=2000。可以利用数组来代替HashMap,数组的优点是:查询效率快,只要保存出现的数和对应的下标就行了,我们可以把数组下标看作key,该下标存储的内容就是该数在原数组的下标,等价于HashMap的value。题目下标要求从1开始,那我们进行查询时,如果不为0,说明之前出现过,为0则未出现过,把该数记录存储下来。

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int a[] = new int[2010];
        int n = numbers.length;
        a[numbers[0]+1000] = 1;
        for(int i = 1; i < n; i++){
            int x = target - numbers[i] + 1000;
            if (a[x] != 0){
                return new int[] {a[x], i+1};
            }
            a[numbers[i]+1000] = i + 1;
        }
        return new int[]{};
    }
}

复杂度分析:

  • 时间复杂度:O(n)
  • 空间复杂度: O(2*n)

解法二利用数组查询效率快,但当数据范围变大时,如 -10^8 <= numbers[i] <= 10^8,那可能无法开辟出如此多的连续内存空间,及时开辟出那也会占用很大内存,且空间利用率也不高。

解法三:双指针

初始时左指针指向第一个元素,右指针指向最后一个元素。每次都计算左右两指针之和,如果该和等于目标值,则直接返回左右指针对应的下标{l+1,r+1};如果该和小于目标值,将左指针右移;如果该和大于目标值,右指针左移;如此往复判断,就可以找到对应下标。

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int i = 0;
        int j = numbers.length - 1;
        while (i < j) {
            int sum = numbers[i] + numbers[j];
            if (sum < target) {
                i++;
            } else if (sum > target) {
                j--;
            } else {
                return new int[]{i+1, j+1};
            }
        }
        return new int[]{};
    }

}

复杂度分析:

  • 时间复杂度:O(n),其中 n 是数组的长度。两个指针移动的总次数最多为 n 次
  • 空间复杂度: O(1)

解法三:与解法二进行比较,该题的数据范围无法体现出双指针的优势,但该种方法无需再内存中开辟连续空间,当数据范围变大时,解法二会超出内存限制,无法运行。综合来看,解法三才是该题的优质解法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值