【算法】两数之和 II - 输入有序数组

90 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第29天,点击查看活动详情

题目

给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列  ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。

以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

你所设计的解决方案必须只使用常量级的额外空间。

解题思路

关键词:非递减顺序排序;下标为1;

关键信息:有序数组;注意下标输出+1;尽量不使用额外空间;

哈希表存储解法

最简单解法是采用一个哈希表来保存每个数组值然后根据target值计算出另外数组值是否存在在该数组中。

  1. 先创建values哈希表;遍历每个数值将target - value的值存入到哈希表中:key = value(该数值):value = i+1(该值下标)
  2. 当遍历过程中出现target - value为key时有对应value值说明该值对应另外一个值也存在。
  3. 当存在两个值时输出对应值的下标,根据题意记得下标+1。
   public int[] twoSum(int[] numbers, int target) {
        Map<Integer,Integer> values = new HashMap<Integer,Integer>();
        for(int i = 0;i < numbers.length; i++){
            int value = numbers[i]; // 本次数值
            int value2 = target - value; // 另外一个值
            if(values.get(value2) != null){ //  另外一个值在哈希表中
                return new int[]{values.get(value2),i+1}; // 两个值都存在并输出
            }else{
                values.put(value,i+1);
            }
        }
        return new int[0];
    }

双指针解法

有序数组遍历常用到双指针解法本题也是如此。前提条件已知数组是非递减数组因此数组首尾值一定是最小和最大的值。双指针解法并是通过首尾数值相加找到符合对应target条件。

  1. 定义双指针下标l和r,初始化分别指向0和length - 1
  2. 循环遍历双指针相加值是否等于target值:当相加值大于target则移动右指针;当相加值小于target则移动左指针。
  3. 双指针一直移动直到相加等于target为止。
 public int[] twoSum(int[] numbers, int target) {
        int length = numbers.length;
        int l = 0, r = length - 1;
        while(numbers[l] + numbers[r] != target){
            if(numbers[l] + numbers[r] > target) r--; // 大了右边指针左移
            if(numbers[l] + numbers[r] < target) l++; // 小了左边指针右移
        }
        return new int[]{l + 1,r + 1};
    }

双指针巧妙之处在于利用有序数组规则(有序,肯定有存在结果,首尾大小等),左右指针移动终究会找到对应结果。

参考