• leetcode哈希表必刷题——有效的字母异位词、两个数组的交集、快乐数、两数之和、四数相加 II、赎金信、三数之和、四数之和


    有效的字母异位词

    题目链接

    给定两个字符串 st ,编写一个函数来判断 t 是否是 s 的字母异位词。

    **注意:**若 st 中每个字符出现的次数都相同,则称 st 互为字母异位词。

    示例 1:

    输入: s = "anagram", t = "nagaram"
    输出: true
    
    • 1
    • 2

    示例 2:

    输入: s = "rat", t = "car"
    输出: false
    
    • 1
    • 2

    提示:

    • 1 <= s.length, t.length <= 5 * 104
    • st 仅包含小写字母

    Python:

    # 数组
    class Solution:
        def isAnagram(self, s: str, t: str) -> bool:
            if len(s) != len(t):
                return False
            c1 = [0] * 26
            c2 = [0] * 26
            for ch in s:
                c1[ord(ch) - ord("a")] += 1
            for ch in t:
                c2[ord(ch) - ord("a")] += 1
            return c1 == c2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    # t 是 s的异位词等价于「两个字符串排序后相等」。因此我们可以对字符串 s 和 t 分别排序,看排序后的字符串是否相等即可判断。此外,如果 s 和 t 的长度不同,t 必然不是 s 的异位词。
    
    class Solution:
        def isAnagram(self, s: str, t: str) -> bool:
            if len(s) != len(t):
                return False
            return sorted(s) == sorted(t)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    class Solution:
        def isAnagram(self, s: str, t: str) -> bool:
            ls, lt = len(s), len(t)
            if ls != lt:
                return False
            h = {}
            for i in range(ls):
                if s[i] in h:
                    h[s[i]] += 1
                else:
                    h[s[i]] = 1
            for i in range(lt):
                if t[i] in h:
                    h[t[i]] -= 1
                    if h[t[i]] < 0:
                        return False
                else:
                    return False
            return True
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    class Solution:
        def isAnagram(self, s: str, t: str) -> bool:
            ls, lt = len(s), len(t)
            if ls != lt:
                return False
            h = defaultdict(int)
            for i in range(ls):
                h[s[i]] += 1
            for i in range(lt):
                h[t[i]] -= 1
                if h[t[i]] < 0:
                    return False
            for i in h.values():
                if i != 0:
                    return False
            return True
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Go:

    //使用数组
    
    func isAnagram(s, t string) bool {
        if len(s) != len(t) {
    		return false
    	}
        var c1, c2 [26]int
        for _, ch := range s {
            c1[ch-'a']++
        }
        for _, ch := range t {
            c2[ch-'a']++
        }
        return c1 == c2
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    //t 是 s的异位词等价于「两个字符串排序后相等」。因此我们可以对字符串 s 和 t 分别排序,看排序后的字符串是否相等即可判断。此外,如果 s 和 t 的长度不同,t 必然不是 s 的异位词。
    
    func isAnagram(s, t string) bool {
    	if len(s) != len(t) {
    		return false
    	}
    	s1, s2 := []byte(s), []byte(t)
    	sort.Slice(s1, func(i, j int) bool { return s1[i] < s1[j] })
    	sort.Slice(s2, func(i, j int) bool { return s2[i] < s2[j] })
    	return string(s1) == string(s2)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    func isAnagram(s string, t string) bool {
    	if len(s) != len(t) {
    		return false
    	}
    	h := make(map[rune]int)
    	for _, char := range s {
    		h[char]++
    	}
    	for _, char := range t {
    		h[char]--
    		if h[char] < 0 {
    			return false
    		}
    	}
    	return true
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    两个数组的交集

    题目链接

    给定两个数组 nums1nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序

    示例 1:

    输入:nums1 = [1,2,2,1], nums2 = [2,2]
    输出:[2]
    
    • 1
    • 2

    示例 2:

    输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
    输出:[9,4]
    解释:[4,9] 也是可通过的
    
    • 1
    • 2
    • 3

    提示:

    • 1 <= nums1.length, nums2.length <= 1000
    • 0 <= nums1[i], nums2[i] <= 1000

    Python:

    class Solution:
        def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
            return list(set(nums1) & set(nums2))
    
    • 1
    • 2
    • 3
    class Solution:
        def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
            return list(set([x for x in nums1 if x in nums2]))
    
    • 1
    • 2
    • 3
    class Solution:
        def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
            nums1 = set(nums1)
            nums2 = set(nums2)
            return [x for x in nums1 if x in nums2]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    class Solution:
        def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
            nums1=set(nums1)
            return [x for x in nums1 if x in nums2]
    
    • 1
    • 2
    • 3
    • 4
    class Solution:
        def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
            vis = {}
            out = []
            for i in nums1:
                vis[i] = False
            for i in nums2:
                if i in vis:
                    vis[i] = True
            for k, v in vis.items():
                if v:
                    out.append(k)
            return out
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Go:

    func intersection(nums1 []int, nums2 []int) []int {
    	vis := make(map[int]bool)
    	out := make([]int, 0)
    	for _, i := range nums1 {
    		vis[i] = false
    	}
    	for _, i := range nums2 {
    		if _, ok := vis[i]; ok {
    			vis[i] = true
    		}
    	}
    	for k, v := range vis {
    		if v == true {
    			out = append(out, k)
    		}
    	}
    	return out
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    快乐数

    题目链接

    编写一个算法来判断一个数 n 是不是快乐数。

    「快乐数」 定义为:

    • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
    • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
    • 如果这个过程 结果为 1,那么这个数就是快乐数。

    如果 n快乐数 就返回 true ;不是,则返回 false

    示例 1:

    输入:n = 19
    输出:true
    解释:
    12 + 92 = 82
    82 + 22 = 68
    62 + 82 = 100
    12 + 02 + 02 = 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    示例 2:

    输入:n = 2
    输出:false
    
    • 1
    • 2

    提示:

    • 1 <= n <= 23^1 - 1

    Python:

    # 哈希表
    class Solution:
        def isHappy(self, n: int) -> bool:
            seen = set()
            while n != 1 and n not in seen:
                seen.add(n)
                n = self.get_sum(n)
            return n == 1
    
        def get_sum(self, n: int):
            _sum = 0
            while n > 0:
                n, digit = divmod(n, 10)
                _sum += digit**2
            return _sum
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    # 双指针法
    class Solution:
        def isHappy(self, n: int) -> bool:
            def step(num):
                _sum = 0
                while num > 0:
                    num, digit = divmod(num, 10)
                    _sum += digit**2
                return _sum
            slow, fast = n, step(n)
            while fast != 1 and slow != fast:
                slow = step(slow)
                fast = step(step(fast))
            return fast == 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Go:

    //哈希表
    func isHappy(n int) bool {
    	seen := make(map[int]bool)
    	for ; n != 1 && !seen[n]; n, seen[n] = getSum(n), true {
    	}
    	return n == 1
    }
    
    func getSum(n int) (sum int) {
    	for n > 0 {
    		sum += (n % 10) * (n % 10)
    		n /= 10
    	}
    	return sum
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    //双指针法
    func isHappy(n int) bool {
        slow, fast := n, step(n)
        for fast != 1 && slow != fast {
            slow = step(slow)
            fast = step(step(fast))
        }
        return fast == 1
    }
    
    func step(n int) int {
        sum := 0
        for n > 0 {
            sum += (n%10) * (n%10)
            n = n/10
        }
        return sum
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    两数之和

    题目链接

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

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

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

    示例 1:

    输入:nums = [2,7,11,15], target = 9
    输出:[0,1]
    解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
    
    • 1
    • 2
    • 3

    示例 2:

    输入:nums = [3,2,4], target = 6
    输出:[1,2]
    
    • 1
    • 2

    示例 3:

    输入:nums = [3,3], target = 6
    输出:[0,1]
    
    • 1
    • 2

    提示:

    • 2 <= nums.length <= 104
    • -109 <= nums[i] <= 109
    • -109 <= target <= 109
    • 只会存在一个有效答案

    Python:

    #暴力解法
    class Solution:
        def twoSum(self, nums: List[int], target: int) -> List[int]:
            n = len(nums)
            for i in range(n):
                for j in range(i + 1, n):
                    if nums[i] + nums[j] == target:
                        return [i, j]
            
            return []
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    #哈希表
    class Solution:
        def twoSum(self, nums: List[int], target: int) -> List[int]:
            hashtable = dict()
            for i, num in enumerate(nums):
                if target - num in hashtable:
                    return [hashtable[target - num], i]
                hashtable[nums[i]] = i
            return []
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Go:

    //暴力解法
    func twoSum(nums []int, target int) []int {
        for i, x := range  nums {
            for j := i + 1; j < len(nums); j++ {
                if x+nums[j] == target {
                    return []int{i, j}
                }
            }
        }
        return nil
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    //哈希表
    func twoSum(nums []int, target int) []int {
        hashTable := map[int]int{}
        for i, x := range nums {
            if p, ok := hashTable[target-x]; ok {
                return []int{p, i}
            }
            hashTable[x] = i
        }
        return nil
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    四数相加 II

    题目链接

    给你四个整数数组 nums1nums2nums3nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

    • 0 <= i, j, k, l < n
    • nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

    示例 1:

    输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
    输出:2
    解释:
    两个元组如下:
    1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
    2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    示例 2:

    输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
    输出:1
    
    • 1
    • 2

    提示:

    • n == nums1.length
    • n == nums2.length
    • n == nums3.length
    • n == nums4.length
    • 1 <= n <= 200
    • -2^28 <= nums1[i], nums2[i], nums3[i], nums4[i] <= 2^28

    Python:

    class Solution:
        def fourSumCount(
            self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]
        ) -> int:
            count = 0
            sum_count = defaultdict(int)
            for i in nums1:
                for j in nums2:
                    sum_count[i + j] += 1
            for i in nums3:
                for j in nums4:
                    count += sum_count[-(i + j)]
            return count
    #四数求和问题一个最常用的优化方法是通过降低复杂度,但这也取决于具体问题的需求。最直接的方法,即四个数组的四次循环,其时间复杂度为O(n^4)。以上述方法通过两次双重循环和哈希表降低了时间复杂度到O(n^2)。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    class Solution:
        def fourSumCount(self, A: List[int], B: List[int], C: List[int], D: List[int]) -> int:
            countAB = collections.Counter(u + v for u in A for v in B)
            ans = 0
            for u in C:
                for v in D:
                    if -u - v in countAB:
                        ans += countAB[-u - v]
            return ans
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Go:

    func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {
    	sumCount := make(map[int]int)
    	count := 0
    	for _, num1 := range nums1 {
    		for _, num2 := range nums2 {
    			sumCount[num1+num2]++
    		}
    	}
    	for _, num3 := range nums3 {
    		for _, num4 := range nums4 {
    			count += sumCount[-(num3 + num4)]
    		}
    	}
    	return count
    }
    //四数求和问题一个最常用的优化方法是通过降低复杂度,但这也取决于具体问题的需求。最直接的方法,即四个数组的四次循环,其时间复杂度为O(n^4)。以上述方法通过两次双重循环和哈希表降低了时间复杂度到O(n^2)。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    赎金信

    题目链接

    给你两个字符串:ransomNotemagazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。

    如果可以,返回 true ;否则返回 false

    magazine 中的每个字符只能在 ransomNote 中使用一次。

    示例 1:

    输入:ransomNote = "a", magazine = "b"
    输出:false
    
    • 1
    • 2

    示例 2:

    输入:ransomNote = "aa", magazine = "ab"
    输出:false
    
    • 1
    • 2

    示例 3:

    输入:ransomNote = "aa", magazine = "aab"
    输出:true 
    
    • 1
    • 2

    提示:

    • 1 <= ransomNote.length, magazine.length <= 10^5
    • ransomNotemagazine 由小写英文字母组成

    Python:

    class Solution:
        def canConstruct(self, ransomNote: str, magazine: str) -> bool:
            if len(ransomNote) > len(magazine):
                return False
            return not collections.Counter(ransomNote) - collections.Counter(magazine)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    #数组,速度最快
    class Solution:
        def canConstruct(self, ransomNote: str, magazine: str) -> bool:
            if len(ransomNote) > len(magazine):
                return False
            cnt = [0] * 26
            for i in magazine:
                cnt[ord(i) - ord("a")] += 1
            for i in ransomNote:
                t = ord(i) - ord("a")
                cnt[t] -= 1
                if cnt[t] < 0:
                    return False
            return True
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    class Solution:
        def canConstruct(self, ransomNote: str, magazine: str) -> bool:
            m = defaultdict(int)
            for i in magazine:
                m[i] += 1
            for i in ransomNote:
                if i in m and m[i]:
                    m[i] -= 1
                else:
                    return False
            return True
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Go:

    //哈希表
    func canConstruct(ransomNote string, magazine string) bool {
        
    	m := make(map[rune]int)
    	for _, v := range magazine {
    		m[v]++
    	}
    	for _, v := range ransomNote {
    		if value, ok := m[v]; ok && value > 0 {
    			m[v]--
    		} else {
    			return false
    		}
    	}
    	return true
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    //数组
    func canConstruct(ransomNote, magazine string) bool {
        if len(ransomNote) > len(magazine) {
            return false
        }
        cnt := [26]int{}
        for _, ch := range magazine {
            cnt[ch-'a']++
        }
        for _, ch := range ransomNote {
            cnt[ch-'a']--
            if cnt[ch-'a'] < 0 {
                return false
            }
        }
        return true
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    三数之和

    题目链接

    给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

    你返回所有和为 0 且不重复的三元组。

    **注意:**答案中不可以包含重复的三元组。

    示例 1:

    输入:nums = [-1,0,1,2,-1,-4]
    输出:[[-1,-1,2],[-1,0,1]]
    解释:
    nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
    nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
    nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
    不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
    注意,输出的顺序和三元组的顺序并不重要。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    示例 2:

    输入:nums = [0,1,1]
    输出:[]
    解释:唯一可能的三元组和不为 0 。
    
    • 1
    • 2
    • 3

    示例 3:

    输入:nums = [0,0,0]
    输出:[[0,0,0]]
    解释:唯一可能的三元组和为 0 。 
    
    • 1
    • 2
    • 3

    提示:

    • 3 <= nums.length <= 3000
    • -10^5 <= nums[i] <= 10^5

    Python:

    #集合法
    class Solution:
        def threeSum(self, nums: List[int]) -> List[List[int]]:
            result = []  # 初始化结果列表
            nums.sort()  # 对输入的列表进行排序
            for i in range(len(nums) - 2):  # 遍历每个元素
                if nums[i] > 0:  # 当前数大于0,由于是排序过的列表,后面的数肯定都大于0,不可能再找到和为0的三个数,因此直接退出循环
                    break
                if i > 0 and nums[i] == nums[i - 1]:  # 当前数和上一个数相同,跳过以避免出现重复的结果
                    continue
                seen = set()  # 初始化一个集合,用来保存已经遍历过的数
                j = i + 1
                while j < len(nums):  # 从当前数的下一个元素开始扫描
                    complement = -(nums[i] + nums[j])  # 计算需要查找的补数值,这个补数值和当前的数与下一个数相加的和应该等于0
                    if complement in seen:  # 如果这个补数值已经在seen集合中,说明找到了一个有效的组合,将其放入结果列表
                        result.append([nums[i], nums[j], complement])
                        # 向后移动指针以避免重复的解决方案
                        while j + 1 < len(nums) and nums[j] == nums[j + 1]:
                            j += 1
                    else:
                        seen.add(nums[j])  # 如果补数值不在seen集合中,将当前的数加入seen集合
                    j += 1
            return result  # 返回结果列表
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    #双指针法
    class Solution:
        def threeSum(self, nums: List[int]) -> List[List[int]]:
            nums.sort()  # 先将数组排序
            result = []  # 结果集
            l = len(nums)
            for i in range(l - 2):  # 遍历数组,为什么是到 l - 2,因为我们需要找的是三个数的组合
                if nums[i] > 0:  # 如果第一个元素已经大于0,不需要进一步检查
                    break
                if i > 0 and nums[i] == nums[i - 1]:  # 如果当前数字和前一个相同,跳过这个数字,防止结果中出现重复的组合
                    continue
                left, right = i + 1, l - 1  # 定义双指针
                while left < right:  # 当左指针小于右指针的时候,执行以下操作
                    total = nums[i] + nums[left] + nums[right]  # 计算三个数的和
                    if total < 0:  # 和小于0,需要增大,所以左指针右移
                        left += 1
                    elif total > 0:  # 和大于0,需要减小,所以右指针左移
                        right -= 1
                    else:  # 和为0,记录这个组合
                        result.append([nums[i], nums[left], nums[right]])
                        left += 1  # 为了寻找下一个可能的组合,左指针右移
                        right -= 1  # 右指针左移
                        while left < right and nums[left] == nums[left - 1]:  # 跳过重复的组合
                            left += 1
                        while left < right and nums[right] == nums[right + 1]:  # 跳过重复的组合
                            right -= 1
            return result  # 返回结果集
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    Go:

    //哈希表
    func threeSum(nums []int) [][]int {
    	var result [][]int
    	sort.Ints(nums)
    	for i := 0; i < len(nums)-2; i++ {
    		if nums[i] > 0 {
    			break
    		}
    		if i > 0 && nums[i] == nums[i-1] {
    			continue
    		}
    		seen := make(map[int]bool)
    		for j := i + 1; j < len(nums); j++ {
    			complement := -(nums[i] + nums[j])
    			if seen[complement] {
    				result = append(result, []int{nums[i], complement, nums[j]})
    				for j+1 < len(nums) && nums[j] == nums[j+1] {
    					j++
    				}
    			}
    			seen[nums[j]] = true
    		}
    	}
    	return result
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    //双指针
    func threeSum(nums []int) [][]int {
    	var result [][]int
    	sort.Ints(nums)
    	l := len(nums)
    	for i := 0; i < l-2; i++ {
    		if nums[i] > 0 {
    			break
    		}
    		if i > 0 && nums[i] == nums[i-1] {
    			continue
    		}
    		left, right := i+1, l-1
    		for left < right {
    			sum := nums[i] + nums[left] + nums[right]
    			if sum < 0 {
    				left++
    			} else if sum > 0 {
    				right--
    			} else {
    				result = append(result, []int{nums[i], nums[left], nums[right]})
    				left++
    				right--
    				for left < right && nums[left] == nums[left-1] {
    					left++
    				}
    				for left < right && nums[right] == nums[right+1] {
    					right--
    				}
    			}
    		}
    	}
    	return result
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    四数之和

    题目链接

    给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

    • 0 <= a, b, c, d < n
    • abcd 互不相同
    • nums[a] + nums[b] + nums[c] + nums[d] == target

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

    示例 1:

    输入:nums = [1,0,-1,0,-2,2], target = 0
    输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
    
    • 1
    • 2

    示例 2:

    输入:nums = [2,2,2,2,2], target = 8
    输出:[[2,2,2,2]]
    
    • 1
    • 2

    提示:

    • 1 <= nums.length <= 200
    • -10^9 <= nums[i] <= 10^9
    • -10^9 <= target <= 10^9

    Python:

    #双指针法
    class Solution:
        def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
            result = []
            nums.sort()
            l = len(nums)
            for i in range(l - 3):
                if i > 0 and nums[i] == nums[i - 1]:
                    continue
                for j in range(l - 1, 2, -1):
                    if j < l - 1 and nums[j] == nums[j + 1]:
                        continue
                    left, right = i + 1, j - 1
                    while left < right:
                        total = nums[i] + nums[j] + nums[left] + nums[right]
                        if total < target:
                            left += 1
                        elif total > target:
                            right -= 1
                        else:
                            result.append([nums[i], nums[j], nums[left], nums[right]])
                            left += 1
                            right -= 1
                            while left < right and nums[left] == nums[left - 1]:
                                left += 1
                            while left < right and nums[right] == nums[right + 1]:
                                right -= 1
            return result
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    #集合法
    class Solution:
        def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
            # 创建频率字典,用于存放每一个数出现的次数
            freq = {}
            for num in nums:
                freq[num] = freq.get(num, 0) + 1
            # 创建存放结果的集合,用于去重
            ans = set()
            # 遍历数组的每一个数
            for i in range(len(nums)):
                # 双层遍历,找到三元组
                for j in range(i + 1, len(nums)):
                    for k in range(j + 1, len(nums)):
                        # 计算需要寻找的值
                        val = target - (nums[i] + nums[j] + nums[k])
                        # 判断需要寻找的值是否在字典中
                        if val in freq:
                            # 计算当前三元组中是否有重复值
                            count = (nums[i] == val) + (nums[j] == val) + (nums[k] == val)
                            # 检查字典中该值的个数是否大于三元组中的个数
                            if freq[val] > count:
                                # 添加到结果集中
                                ans.add(tuple(sorted([nums[i], nums[j], nums[k], val])))
            # 返回格式化后的结果
            return [list(x) for x in ans]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    Go:

    //双指针法,可类比三数之和这道题
    func fourSum(nums []int, target int) [][]int {
    	var result [][]int
    	sort.Ints(nums)
    	l := len(nums)
    	for i := 0; i < l-3; i++ {
    		if i > 0 && nums[i] == nums[i-1] {
    			continue
    		}
    		for j := l - 1; j > 2; j-- {
    			if j < l-1 && nums[j] == nums[j+1] {
    				continue
    			}
    			for left, right := i+1, j-1; left < right; {
    				sum := nums[i] + nums[j] + nums[left] + nums[right]
    				if sum < target {
    					left++
    				} else if sum > target {
    					right--
    				} else {
    					result = append(result, []int{nums[i], nums[j], nums[left], nums[right]})
    					left++
    					right--
    					for left < right && nums[left] == nums[left-1] {
    						left++
    					}
    					for left < right && nums[right] == nums[right+1] {
    						right--
    					}
    				}
    			}
    		}
    	}
    	return result
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    //硬用哈希表,不建议
    func fourSum(nums []int, target int) [][]int {
    	freq := make(map[int]int)
    	for _, num := range nums {
    		freq[num] = freq[num] + 1
    	}
    	var ans [][]int
    	for i := 0; i < len(nums); i++ {
    		for j := i + 1; j < len(nums); j++ {
    			for k := j + 1; k < len(nums); k++ {
    				val := target - (nums[i] + nums[j] + nums[k])
    				if _, ok := freq[val]; ok {
    					count := 0
    					if nums[i] == val {
    						count++
    					}
    					if nums[j] == val {
    						count++
    					}
    					if nums[k] == val {
    						count++
    					}
    					if freq[val] > count {
    						quadruplet := []int{nums[i], nums[j], nums[k], val}
    						sort.Ints(quadruplet)
    						if !contains(ans, quadruplet) {
    							ans = append(ans, quadruplet)
    						}
    					}
    				}
    			}
    		}
    	}
    	return ans
    }
    
    func contains(quadruplets [][]int, quadruplet []int) bool {
    	for _, q := range quadruplets {
    		if equal(q, quadruplet) {
    			return true
    		}
    	}
    	return false
    }
    
    func equal(a, b []int) bool {
    	if len(a) != len(b) {
    		return false
    	}
    	for i, v := range a {
    		if v != b[i] {
    			return false
    		}
    	}
    	return true
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
  • 相关阅读:
    【已解决】Splunk 8.2.X 升级ES 后红色报警
    【Unity】简单的深度虚化shader
    Ubuntu 22.04 国内源
    InVEST实践与进阶及在生态系统服务供需、固碳、城市热岛、论文写作
    为什么基于项目的工作是工作的未来?如何管理项目执行?
    【Selenium2+python】自动化unittest生成测试报告
    Spring Cloud Gateway 集成Sa-Token
    基于SpringBoot的校园点餐系统
    进入docker容器内部使用命令行工具
    Brachistochrone:使用变分法找到最快下降曲线
  • 原文地址:https://blog.csdn.net/m0_63230155/article/details/134484169