[LeetCode两数之和] | 刷题打卡

275 阅读2分钟

前言:

一直有刷题习惯,最近才看到掘金举办了刷题活动,特来参加!

掘金团队号上线,助你 Offer 临门! 点击 查看详情

一、题目描述:

两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

样例1:
给出 numbers = [2, 7, 11, 15], target = 9, 返回 [0, 1].
样例2:
给出 numbers = [15, 2, 7, 11], target = 9, 返回 [1, 2].

二、思路分析:

方法描述时间复杂度空间复杂度
双指针法先排序后双指针O(nlogn)O(nlogn)O(n)O(n)
哈希表法根据num[i],找targe-num[i]O(n)O(n)O(n)O(n)

哈希表法

遍历i次,每一次都去查哈希表中是否存在target-nums[i],存在则返回positioni,不存在则存入哈希表. 伪代码如下:

    for... 
        searchkey = target - nums[i]
        if hashmap.containsKey(searchkey )
            return hashmap.get(searchkey ),i
        else
            hashmap.put(nums[i])

双指针

然后对数组排序,在排序后的数组中利用双指针从左右向中间寻找

  • 如果numbers[i] + numbers [j] == target 说明找到答案
  • 如果numbers[i] + numbers [j] < target 说明当前和比答案小。左指针右移
  • 如果numbers[i] + numbers [j] > target 说明当前和比答案大。右指针左移

然后在拷贝数组中找到对应numbers[i]和numbers[j] 的下标,对这两个下标排个序

三、AC 代码:

哈希表法

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;

/*
 * @lc app=leetcode.cn id=1 lang=java
 *
 * [1] 两数之和
 */

// @lc code=start
class Solution {

    /**
     * 
     * @param nums
     * @param target
     * @return fix bug need origin index ;is not value
     */
    public int[] twoSum(int[] nums, int target) {
        // key : origin value
        // value: position
        HashMap<Integer, Integer> hashMap = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int searchValue = target - nums[i];
            if(hashMap.containsKey(searchValue)){
                int[] res = {hashMap.get(searchValue),i};
                return res;
            }
            hashMap.put(nums[i],i);
        }
        return new int[]{-1,-1};
    }
}
// @lc code=end

双指针法

/*
 * @lc app=leetcode.cn id=1 lang=java
 *
 * [1] 两数之和
 */

// @lc code=start
class Solution {
    /**
     * key: origin value value: origin position
     */
     class NumMap {
        Integer currentNum = 0;
        Integer currentIndex = 0;

        public NumMap(Integer number, Integer position) {
            this.currentNum = number;
            this.currentIndex = position;
        }

        public Integer getCurrentNum() {
            return this.currentNum;
        }
    }

    class ValueComparator implements Comparator<NumMap> {
        @Override
        public int compare(NumMap o1, NumMap o2) {
            return o1.getCurrentNum().compareTo(o2.getCurrentNum());
        }

    }

    /**
     * 
     * @param nums
     * @param target
     * @return fix bug need origin index ;is not value
     */
    public int[] twoSum(int[] nums, int target) {
        // back conditions
        int[] result = new int[] { -1, -1 };
        if (nums == null) {
            return result;
        }

        NumMap[] list = new NumMap[nums.length];
        for (int i = 0; i < nums.length; i++) {
            NumMap numMap = new NumMap(nums[i], i);
            list[i] = numMap;
        }
        Arrays.sort(list, new ValueComparator());

        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            int currentSum = list[left].getCurrentNum() + list[right].getCurrentNum();
            if (currentSum == target) {
                result[0] = Math.min(list[left].currentIndex, list[right].currentIndex);
                result[1] = Math.max(list[left].currentIndex, list[right].currentIndex);
                break;
            } else if (currentSum < target) {
                left++;
            } else {
                right--;
            }
        }
        return result;
    }
}
// @lc code=end

总结

主要使用了哈希表法和双指针两种方法做这道题目。

  • 双指针的时间复杂度是O(nlogn)O(nlogn),空间复杂度是O(n)O(n)
  • 哈希表法的时间复杂度是O(n)O(n),空间复杂度是O(n)O(n) 空间和时间上两者差距并不大,仔细比较区别的话,两者最主要区别是:
  1. 双指针需要数组提前排好序,哈希表法对原数组是否有序不作要求
  2. 哈希表法需要使用临时的hashmap去存储以及判等,双指针需要使用自定义对象,判等排序