LeetCode 查找表专题 5:灵活选择键值:4Sum II

LeetCode 查找表专题 5:灵活选择键值:4Sum II

例1:LeetCode 第 454 题:四数相加 II

传送门:英文网址:454. 4Sum II ,中文网址:454. 四数相加 II

给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0

为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范围在 -228 到 228 - 1 之间,最终结果不会超过 。

例如:

输入:
A = [ 1, 2]
B = [-2,-1]
C = [-1, 2]
D = [ 0, 2]

输出:
2

解释:
两个元组如下:
1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0

分析:其实思路只要清楚了,是个很简单的问题。把 A、B、C、D 分成两组,在 A、B 之和中找与 C、D 的相反数之和相同的组合数,要使用 HashMap 这个数据结构。考察了组合数,乘法计数原理。代码编写有技巧,一定要会。

Python 代码1:在理解的基础上记住

class Solution:
    def fourSumCount(self, A, B, C, D):
        """
        :type A: List[int]
        :type B: List[int]
        :type C: List[int]
        :type D: List[int]
        :rtype: int
        """

        map1 = self.get_map(A, B)
        map2 = self.get_map(C, D)
        res = 0

        for key1 in map1:
            if -key1 in map2:
                res += map1[key1] * map2[-key1]
        return res

    def get_map(self, tuple1, tuple2):
        map = dict()
        for num1 in tuple1:
            for num2 in tuple2:
                map[num1 + num2] = (map.setdefault(num1 + num2, 0) + 1)
        return map

Python 代码2:下面这种写法省下一个 map,不过在计算的时候,就不能用乘法了,只能用加法,就这点区别

class Solution:
    def fourSumCount(self, A, B, C, D):
        """
        :type A: List[int]
        :type B: List[int]
        :type C: List[int]
        :type D: List[int]
        :rtype: int
        """

        map = dict()
        for num3 in C:
            for num4 in D:
                map[num3 + num4] = (map.setdefault(num3 + num4, 0) + 1)

        res = 0

        for num1 in A:
            for num2 in B:
                s = num1 + num2
                if -s in map:
                    res += map[-s]
        return res

Java 代码:同上

/* 分治,把4个list,拆成两两组合,降低complexity
* Time complexity: O(n^2), space complexity: O(n^2) */
class Solution {
    public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {
        Map<Integer, Integer> hm = new HashMap<>();
        for (int i = 0; i < A.length; i++) {
            for (int j = 0; j < B.length; j++) {
                hm.put(A[i] + B[j], hm.getOrDefault(A[i] + B[j], 0) + 1);
            }
        }
        int res = 0;
        for (int i = 0; i < C.length; i++) {
            for (int j = 0; j < D.length; j++) {
               res += hm.getOrDefault((C[i] + D[j]) * -1, 0);
            }
        }
        return res;
    }
}

练习 :例题:LeetCode 第 49 题:字母异位词分组

传送门:英文网址:49. Group Anagrams ,中文网址:49. 字母异位词分组

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]

说明:

  • 所有输入均为小写字母。
  • 不考虑答案输出的顺序。

思路1:用 map 就可以完成,key 是 sort 以后的字符。

414598-7ccbf0afff350829.png
image

Python 代码:

class Solution:
    def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """
        map = dict()

        if len(strs) == 0:
            return []

        for s in strs:
            key = ''.join(sorted(list(s)))
            if key not in map:
                map[key] = [s]
            else:
                map[key].append(s)

        return list(map.values())

在官方题解下看到的解答,直接拿 tuple 就可以作为哈希表的 key。

Python 代码:

class Solution(object):
    def groupAnagrams(self, strs):
        ans = collections.defaultdict(list)
        for s in strs:
            ans[tuple(sorted(s))].append(s)
        return ans.values()

下面这个解法本质上没有变,只是 key 不一样了。

414598-84b9e5354d97ad87.png
image

注意到英文字母只有 26 个,因此如果不排序的话,直接统计字母频率也是可以的,把字母频率数组变成 tuple 作为哈希表的 key。

Python 代码:

class Solution:
    def groupAnagrams(strs):
        ans = collections.defaultdict(list)
        for s in strs:
            count = [0] * 26
            for c in s:
                count[ord(c) - ord('a')] += 1
            ans[tuple(count)].append(s)
        return ans.values()

思路2:可以给同构异形体做编码,编码一样的就应该在一组里面。很多时候,hash 表的功能可以用数组代替。下面的两版代码时间复杂度太高,了解一下有这个思路就可以了。

Python 代码:

class Solution:
    def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """
        # 26 个质数
        primes = [2, 3, 5, 7, 11,
                  13, 17, 19, 23, 29,
                  31, 37, 41, 43, 47,
                  53, 59, 61, 67, 71,
                  73, 79, 83, 89, 97,
                  101]

        # hash_arr 中存放的是与 res 对应的 hash 值
        hash_arr = []
        res = []

        for s in strs:
            hash_val = 1
            for alpha in s:
                hash_val *= primes[ord(alpha) - ord('a')]
            index = 0
            while index < len(hash_arr):
                if hash_arr[index] == hash_val:
                    res[index].append(s)
                    break
                index += 1
            if index == len(hash_arr):
                hash_arr.append(hash_val)
                res.append([s])
        return res


if __name__ == '__main__':
    strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
    solution = Solution()
    result = solution.groupAnagrams(strs)
    print(result)

Python 代码:

class Solution:
    def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """
        # 26 个质数
        primes = [2, 3, 5, 7, 11,
                  13, 17, 19, 23, 29,
                  31, 37, 41, 43, 47,
                  53, 59, 61, 67, 71,
                  73, 79, 83, 89, 97,
                  101]

        # hash_arr 中存放的是与 res 对应的 hash 值
        hash_arr = []
        res = []

        for s in strs:
            hash_val = 1
            for alpha in s:
                hash_val *= primes[ord(alpha) - ord('a')]

            found = False
            index = 0
            while index < len(hash_arr):
                if hash_arr[index] == hash_val:
                    res[index].append(s)
                    found = True
                    break
                index += 1
            # 如果没有找到,就加在后面,hash_arr 和 res 是同步的
            if not found:
                hash_arr.append(hash_val)
                res.append([s])
        return res

(本节完)

猜你喜欢

转载自blog.csdn.net/weixin_34258078/article/details/90885261