LeetCode刷题系列—1.TowSum 求和为给定值的两个数

131 阅读1分钟

1.题目描述

英文版:

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].

中文版:

在一个整型数组中,返回该数组中两个相加起来等于某个特定值的元素。

假设每一次输入都有唯一特定的结果,并且你不能使用同一个元素两次。

例如:

数组: nums = [2,7,11,15],target = 9,

因为 nums[0] + nums[1] = 2 + 7 = 9, 所以 return [0,1]

2.解法

2.1 解法1

思路:

第一次做LeetCode题目,看完这个题目之后。第一个想法就是使用暴力破解法,就是使用双重循环把每个数都分别进行两两相加,如果相加结果等于target时,则退出循环,返回结果。但是这种解法时间复杂度很高,接近O(n x n)。

    /**
     * 方式1:两层遍历
     */
    public static int[] towSum1(int[] arr,int target){
        int[] res = new int[2];
        ok : for(int i = 0;i < arr.length;i++){
            for(int j = i + 1;j < arr.length;j++){
                if(arr[i] + arr[j] == target){
                    res[0] = i;
                    res[1] = j;
                    break ok;
                }
            }
        }
        return res;
    }

在LeetCode上运行的结果:

2.2 解法2

思路

看了网上很多大神的博客和公众号之后,发现可以使用HashMap进行处理。

第一遍循环先把数组存到HashMap中,第二次循环再通过map.get(map.get(target - nums[i]))看能不能拿到相应的角标值,并且拿到的角标值不能等于i。

如果符合这两个条件,则说明角标为i和map.get(target - nums[i])对应的元素正是相加起来等于tartget的两个元素。这里也用到了两次循环,但是不是双重循环,是两个单层循环。

并且在不考虑hash冲突的情况下,HashMap取值的时间复杂度约等于O(1),所以整个算法的时间复杂度约为O(n)。

    /**
     * 方式2:两个单层循环,使用map缓存辅助
     */
    public static int[] towSum2(int[] arr,int target){
        int[] res = new int[2];
        Map<Integer,Integer> map = new HashMap<>();
        //第一层循环
        // 将数组循环放入map中,key对应数组的值,value对应数组的角标
        for(int i = 0;i < arr.length;i++){
            map.put(arr[i],i);
        }

        //第二层循环
        //循环将数据中的数拿出来,与map中的数进行匹配
        for(int j = 0;j < arr.length;j++){
            //如果map中存在target - arr[j]的数,则说明找到两个目标值的下标:j和map.get(target - arr[j])
            //但是需要注意的是,map.get(target - arr[j])的值不能是j本身
            if(map.get(target - arr[j]) != null
                    && map.get(target - arr[j]) != j){
                res[0] = j;
                res[1] = map.get(target - arr[j]);
                break;
            }
        }

        return res;
    }

在LeetCode上运行的结果:

2.3 解法3

思路:

解法3是在解法2的基础上进行相应的优化,即可以把两个循环简化成为一个循环,一边循环比较,一边把元素put到HashMap中。

但是这里需要注意的是,put元素需在比较之后执行,否则会有问题。

    /**
     * 方式3:单层循环,使用map缓存辅助
     */
    public static int[] towSum3(int[] arr,int target){
        int[] res = new int[2];
        Map<Integer,Integer> map = new HashMap<>();

        for(int i = 0;i < arr.length;i++){
            if(map.get(target - arr[i]) != null){
                res[0] = i;
                res[1] = map.get(target - arr[i]);
                break;
            }

            map.put(arr[i],i);
        }

        return res;
    }

在LeetCode上运行的结果:

3.测试

在本地,我只是简单写了一个main函数来对它进行测试。但这些代码都已经在LeetCode上运行通过。

public static void main(String[] args) {
    int[] nums = {3,3};
    int target = 6;
    int [] result = twoSum3(nums,target);
    System.out.println(result[0]+"---"+result[1]);
}
欢迎关注个人公众号,可直接扫描以下二维码或微信搜索“阿毛聊技术”进行关注。