Leetcode 2sum,以及一些衍生题目的总结;

今天主要将自己刷的2sum和相关的一些同一类型的题目做个summary。
正所谓‘平生不识TwoSum,刷尽LeetCode也枉然’

1. 2sum

题目描述:
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].

这道题目, 为了提升时间的复杂度,需要用空间来换取,这里我用线性的时间复杂度来解决这道问题,所以先遍历一个数,另外一个数字先存起来,这里用到HashMap,来建立数字和其坐标位置之间的映射,我们都知道HashMap是常数级的查找效率,这样,我们在遍历数组的时候,用target减去遍历到的数字,就是另一个需要的数字了,直接在HashMap中查找其是否存在即可,注意要判断查找到的数字不是第一个数字,比如target是4,遍历到了一个2,那么另外一个2不能是之前那个2,整个实现步骤为:先遍历一遍数组,建立HashMap映射,然后再遍历一遍,开始查找,找到则记录index。代码如下:

// Time O(n)  Space O(n)
// Since the hash table reduces the lookup time to O(1), the time complexity is O(n)
class Solution {
    public int[] twoSum(int[] nums, int target) {
        // corner case
        if(nums == null || nums.length < 2) {
            return new int[]{-1, -1};
        }
        Map<Integer, Integer> map = new HashMap<>();
        int[] res = new int[2];
        for(int i = 0; i < nums.length; i++) {
            if(map.containsKey(target - nums[i])) {
                res[0] = map.get(target - nums[i]);
                res[1] = i;
                break;
            }
            map.put(nums[i], i);
        }
        return res;
    }
}

参考资料:http://www.cnblogs.com/grandyang/p/4130379.html

167. Two Sum II - Input array is sorted

Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.

Note:

  1. Your returned answers (both index1 and index2) are not zero-based.
  2. You may assume that each input would have exactly one solution and you may not use the same element twice.
Example:
Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.

// Time complexity : O(n), Space complexity: O(n); it likes the 2sum.
class Solution {
    public int[] twoSum(int[] numbers, int target) {
        if(numbers == null || numbers.length < 2) {
            return new int[]{-1, -1};
        }
        Map<Integer, Integer> map = new HashMap<>();
        int[] res = new int[2];
        for(int i = 0; i < numbers.length; i++) {
            if(map.containsKey(target - numbers[i])) {
                res[0] = map.get(target - numbers[i]) + 1;
                res[1] = i + 1;
            }
            map.put(numbers[i], i);
        }
        return res;
    }
}

// Time complexity : O(n). Each of the n elements is visited at most once, thus the time complexity is O(n).
// Space complexity : O(1). We only use two indexes, the space complexity is O(1).
/*
1. 这里给的整数数组是按照升序排列的,所以可以利用升序的性质,用O(n)的时间复杂度完成。
2. 这里首先用两个指针分别指向数组的第一个元素和最后一个元素,之后将指针指向的两个元素相加并与target作
比较,若相等,则得到结果存到indices中并退出循环;否则若两者相加之和大于target,则将第二个指针向前
移动一位,若两者相加之和小于target,则将第一个指针向后移动一位。
3. 这里返回的indices的位置需要加1,因为题目要求数组下标不能从0开始。
*/
class Solution {
    public int[] twoSum(int[] numbers, int target) {
        if(numbers == null || numbers.length < 2) {
            return new int[]{-1, -1};
        }
        int[] res = new int[2];
        int low = 0, high = numbers.length - 1;
        while(low < high) {
            if(numbers[low] + numbers[high] == target) {
                res[0] = low + 1;
                res[1] = high + 1;
                return res;
            }else if(numbers[low] + numbers[high] < target) {
                low++;
            }else {
                high--;
            }
        }
        return res;
    }
}

170. Two Sum III - Data structure design

Design and implement a TwoSum class. It should support the following operations: add and find.

add - Add the number to an internal data structure.
find - Find if there exists any pair of numbers which sum is equal to the value.

Example 1:
add(1); add(3); add(5);
find(4) -> true
find(7) -> false

Example 2:
add(3); add(1); add(2);
find(3) -> true
find(6) -> false
class TwoSum {
    /** Initialize your data structure here. */
    Map<Integer, Integer> map;
    public TwoSum() {
        map = new HashMap<>();
    }
    /** Add the number to an internal data structure.. */
    public void add(int number) {
        if(map.containsKey(number)) {
            map.put(number, map.get(number) + 1);
        }else {
            map.put(number, 1);
        }
    }
    /** Find if there exists any pair of numbers which sum is equal to the value. */
    public boolean find(int value) {
        // get keyset value from map
        // for (Map.Entry<Integer, Integer> entry : map.entrySet()) entrySet()
        for(int key: map.keySet()) {
            int another = value - key;
            if(another == key && map.get(another) > 1) {
                return true;
            }else if(another != key && map.containsKey(another)) {
                return true;
            }
        }
        return false;
    }
}
/**
 * Your TwoSum object will be instantiated and called as such:
 * TwoSum obj = new TwoSum();
 * obj.add(number);
 * boolean param_2 = obj.find(value);
 */

653. Two Sum IV - Input is a BST

Given a Binary Search Tree and a target number, return true if there exist two elements in the BST such that their sum is equal to the given target.

Example 1:
Input: 
    5
   / \
  3   6
 / \    \
2   4    7
Target = 9
Output: True

Example 2:
Input: 
    5
   / \
  3   6
 / \    \
2   4    7
Target = 28
Output: False
  1. Using HashSet[Accepted]
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
// Time complexity : O(n). The entire tree is traversed only once in the worst case. 
// Here, n refers to the number of nodes in the given tree.
// Space complexity : O(n). The size of the setset can grow upto nn in the worst case.
class Solution {
    public boolean findTarget(TreeNode root, int k) {
        Set<Integer> set = new HashSet<>();
        return helper(root, k, set);
    }
    public boolean helper(TreeNode node, int k, Set<Integer> set) {
        if(node == null) {
            return false;
        }
        if(set.contains(k - node.val)) {
            return true;
        }
        set.add(node.val);
        return helper(node.left, k, set) || helper(node.right, k, set);
    }
}

https://leetcode.com/problems/two-sum-iv-input-is-a-bst/solution/

  1. Using BFS and HashSet [Accepted]
    In this approach, the idea of using the set is the same as in the last approach. But, we can carry on the traversal in a Breadth First Search manner, which is a very common traversal method used in Trees. The way BFS is used can be summarized as given below. We start by putting the root node into a queue. We also maintain a set similar to the last approach. Then, at every step, we do as follows:

    1). Remove an element, p, from the front of the queue.
    2). Check if the element k−p already exists in the set. If so, return True.
    3). Otherwise, add this element, p to the set. Further, add the right and the left child nodes of the current node to the back of the queue
    Continue steps 1. to 3. till the queue becomes empty.
    4). Return false if the queue becomes empty
    5). By following this process, we traverse the tree on a level by level basis.

class Solution {
    public boolean findTarget(TreeNode root, int k) {
        Set<Integer> set = new HashSet<>();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while(!queue.isEmpty()) {
            if(queue.peek() != null) {
                TreeNode node = queue.remove();
                if(set.contains(k - node.val)) {
                    return true;
                }
                set.add(node.val);
                queue.add(node.left);
                queue.add(node.right);
            }else {
                queue.remove();
            }
        }
        return false;
    }
}
  1. inOrder Travelsal (Using BST [Accepted])
// inOrder travelsal
// Runtime: 2 ms
// Memory Usage: 37.1 MB
// the run time is the most fast in this three ways;
class Solution {
    public boolean findTarget(TreeNode root, int k) {
        List<Integer> list = new ArrayList<>();
        inOrder(root, list);
        int low = 0, high = list.size() - 1;
        while(low < high) {
            int sum = list.get(low) + list.get(high);
            if(sum == k) {
                return true;
            }else if(sum < k) {
                low++;
            }else {
                high--;
            }
        }
        return false;
    }
    public void inOrder(TreeNode root, List<Integer> list) {
        if(root == null) {
            return;
        }
        inOrder(root.left, list);
        list.add(root.val);
        inOrder(root.right, list);
    }
}

288. Unique Word Abbreviation

题目描述:https://leetcode.com/problems/unique-word-abbreviation/description/

// Time complexity : O(n) for each isUnique call. Assume that n is the number of words in the dictionary, 
// each isUnique call takes O(n) time.
class ValidWordAbbr {
    private final String[] dict;

    public ValidWordAbbr(String[] dictionary) {
        dict = dictionary;
    }
    public boolean isUnique(String word) {
        int n = word.length();
        for(String s: dict) {
            if(word.equals(s)) continue;
            int m = s.length();
            if(n == m && s.charAt(0) == word.charAt(0) && s.charAt(m - 1) == word.charAt(n - 1)) {
                return false;
            }
        }
        return true;
    }
}

/**
 * Your ValidWordAbbr object will be instantiated and called as such:
 * ValidWordAbbr obj = new ValidWordAbbr(dictionary);
 * boolean param_1 = obj.isUnique(word);
 */
/*
Time complexity : O(n) pre-processing, O(1) for each isUnique call. 
Both Approach #2 and Approach #3 above take O(n) pre-processing time in the constructor. 
This is totally worth it if isUnique is called repeatedly.

Space complexity : O(n). We traded the extra O(n) space storing the table to reduce the time complexity in isUnique.
*/

class ValidWordAbbr {
    private final Map<String, Set<String>> abbrDict = new HashMap<>();
    
    public ValidWordAbbr(String[] dictionary) {
        for(String s: dictionary) {
            String abbr = toAbbr(s);
            Set<String> words = abbrDict.containsKey(abbr) ? abbrDict.get(abbr) : new HashSet<>(); // new HashSet<>()
            words.add(s);
            abbrDict.put(abbr, words);
        }
    }
    
    public boolean isUnique(String word) {
        String abbr = toAbbr(word);
        Set<String> words = abbrDict.get(abbr);
        return words == null || (words.size() == 1 && words.contains(word)); // notice
    }
    
    public String toAbbr(String s) {
        int n = s.length();
        if(n <= 2) return s;
        return s.charAt(0) + Integer.toString(n - 2) + s.charAt(n - 1);
    }
}

560. Subarray Sum Equals K

Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k.

Example 1:
Input:nums = [1,1,1], k = 2
Output: 2

Note:
The length of the array is in range [1, 20,000].
The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7].
// Time complexity : O(n^2) Considering every possible subarray takes O(n^2)time. 
// Finding out the sum of any subarray takes O(1) time after the initial processing of O(n) for creating the cumulative sum array.
// Space complexity : O(n). Cumulative sum array sumsum of size n+1 is used.
class Solution {
    public int subarraySum(int[] nums, int k) {
        int count = 0;
        int[] sums = new int[nums.length + 1];
        sums[0] = 0;
        for(int i = 1; i <= nums.length; i++) {
            sums[i] = sums[i - 1] + nums[i - 1];
        }
        for(int start = 0; start < nums.length; start++) {
            for(int end = start + 1; end <= nums.length; end++) {
                if(sums[end] - sums[start] == k) {
                    count++;
                }
            }
        }
        return count;
    }
}

// Time complexity : O(n^2) We need to consider every subarray possible.
// Space complexity : O(1). Constant space is used.
class Solution {
    public int subarraySum(int[] nums, int k) {
        int count = 0;
        int sum = 0;
        for(int i = 0; i < nums.length; i++) {
            sum = nums[i];
            if(sum == k) count++;
            for(int j = i + 1; j < nums.length; j++) {
                sum += nums[j];
                if(sum == k) count++;
            }
        }
        return count;
    }
}

论坛上大家比较推崇的其实是这种解法,用一个哈希表来建立连续子数组之和跟其出现次数之间的映射,初始化要加入{0,1}这对映射,这是为啥呢,因为我们的解题思路是遍历数组中的数字,用sum来记录到当前位置的累加和,我们建立哈希表的目的是为了让我们可以快速的查找sum-k是否存在,即是否有连续子数组的和为sum-k,如果存在的话,那么和为k的子数组一定也存在,这样当sum刚好为k的时候,那么数组从起始到当前位置的这段子数组的和就是k,满足题意,如果哈希表中事先没有m[0]项的话,这个符合题意的结果就无法累加到结果res中,这就是初始化的用途。上面讲解的内容顺带着也把for循环中的内容解释了,这里就不多阐述了,有疑问的童鞋请在评论区留言哈,参见代码如下:

class Solution {
    public int subarraySum(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        map.put(0, 1);
        int sum = 0, count = 0;
        for(int i = 0; i < nums.length; i++) {
            sum += nums[i];
            if(map.containsKey(sum - k)) {
                count += map.get(sum - k);
            }
            map.put(sum, map.getOrDefault(sum, 0) + 1);
        }
        return count;
    }
}

参考文章:http://www.cnblogs.com/grandyang/p/6810361.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352