zoukankan      html  css  js  c++  java
  • 【LeetCode】1、两数之和

    题目等级:Two Sum(Easy)

    题目描述:

      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].
    

      题意:给定一个整数数组和一个指定的数,在数组找两个数使得他们的和等于这个特定数,返回他们的索引,注意一个元素不能重复使用。


    解题思路:

      本题实际比较简单,我们给出以下三种解法:

      解法一:暴力法

      这个解法就很直观了,要找两个数使其等于给定的target,两层循环当然是最暴力的解法,时间复杂度是O(n^2),没有使用额外空间,代码如下:

    class Solution {
        public int[] twoSum(int[] nums, int target) {
            int[] res=new int[]{-1,-1};
            for(int i=0;i<nums.length;i++){
                for(int j=i+1;j<nums.length;j++){
                    if(nums[i]+nums[j]==target){
                        res[0]=i;
                        res[1]=j;
                        break;
                    }
                }
            }
            return res;
        }
    }
    

      解法二:HashMap的引入,两遍遍历

      最简单的算法往往并不是最优的,上面的暴力解法用了两层循环,平方的时间复杂度往往不是我们最喜欢的,我们考虑能不能去掉一层循环。也就是说,当给定一个target,给定一个数nums[i],我们能不能不遍历直接找到有没有另一个加数,很明显,只需要判断数组中有没有target-nums[i]即可。

      我们可以将数组中的数保存到hashMap中,借助HashMap的查找优势来解决,将元素值作为key,索引作为value,则常数时间我们就可以判断其中是否有target-nums[i]这个key值。

      唯一需要注意的地方就是同一个元素不能重复使用。由于去掉了一层循环,因此时间复杂度变为O(n),但是这是用一个长度为n的hashmap换来的,空间复杂度为O(n),相当于一种典型的用空间换时间的算法。

    class Solution {
        public int[] twoSum(int[] nums, int target) {
            int[] res=new int[]{-1,-1};
            Map<Integer,Integer> map=new HashMap<Integer,Integer>();
            for(int i=0;i<nums.length;i++){
                map.put(nums[i],i);
            }
            for(int i=0;i<nums.length;i++){
                if(map.containsKey(target-nums[i]) && map.get(target-nums[i])!=i ){
                    res[0]=i;
                    res[1]=map.get(target-nums[i]);
                    break;
                }
            }
            return res;
        }
    }
    

      解法三:HashMap的改进,一次遍历

      上述解法二,我们可以看到对数组进行了两次遍历,第一次将其存入哈希表,第二次寻找满足条件的元素,实际上这两次循环可以合为一次,即一边存一边寻找满足条件的值。

      当我们遍历到一个元素nums[i]时,可以先判断是否在哈希表中包含target-nums[i],如果存在就相当于已经找到了,不存在则将其加入哈希表,这样做的好处还有一个就是不需要判断是否重复,因为当前元素还没有加入哈希表。

      这和解法二相比实际上是一个微小的改动,时间复杂度和空间复杂度都仍为O(n)。

    class Solution {
        public int[] twoSum(int[] nums, int target) {
            /*改进:一遍遍历,利用哈希的查找优势,空间换时间*/
            int[] res=new int[]{-1,-1};
            Map<Integer,Integer> map=new HashMap<>();
            for(int i=0;i<nums.length;i++){
                int another=target-nums[i];
                //注意:num还没有进哈希表,这样可以避免有重复元素的情况
                if(map.containsKey(another)){ //包含target-num,则找到了对应的值
                    res[0]=map.get(another); //在哈希表中的是第一个
                    res[1]=i;
                    break;
                }
                map.put(nums[i],i); //<元素,下标>   
            }
            return res;
        }
    }
    

    总结:

      本题实际比较简单。重点就在于利用hashmap的空间来换时间。

  • 相关阅读:
    网络基础
    SQL注入
    OpenID说明
    Linux网络编程
    Linux的僵尸进程产生原因及解决方法
    计算机系统的存储层次
    Java实现SSO
    JD(转载)
    Switch的表达式的要求
    leetcode(23. Merge k Sorted Lists)
  • 原文地址:https://www.cnblogs.com/gzshan/p/10955297.html
Copyright © 2011-2022 走看看