【代码随想录记录Day07】--哈希表(454,383,15,18)

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 。所有整数的范围在 -2^28 到 2^28 - 1 之间,最终结果不会超过 2^31 - 1 。

哈希法:(4个独立数组可分为两组(两两相加) 减少时间复杂度,须保存出现的数及数出现的次数,故须采用map

python 版

class Solution(object):
    def fourSumCount(self, nums1, nums2, nums3, nums4):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :type nums3: List[int]
        :type nums4: List[int]
        :rtype: int
        """
        hashmap = dict()
        for n1 in nums1:
            for n2 in nums2:
                if n1+n2 in hashmap:
                    hashmap[n1+n2] += 1
                else:
                    hashmap[n1+n2] = 1
        
        count = 0
        for n3 in nums3:
            for n4 in nums4:
                if -n3-n4 in hashmap:
                    count += hashmap[-n3-n4]
        return  count

JS版

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @param {number[]} nums3
 * @param {number[]} nums4
 * @return {number}
 */
var fourSumCount = function(nums1, nums2, nums3, nums4) {
    const hashmap = new Map();
    for(const n1 of nums1){
        for(const n2 of nums2){
            const sum = n1 + n2;
            hashmap.set(sum,(hashmap.get(sum)||0)+1)
        }
    }
    let count = 0;
    for(const n3 of nums3){
        for(const n4 of nums4){
            const sum = n3 + n4;
            count += (hashmap.get(0-sum)||0)
        }
    }
    return count;

};

383.赎金

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/ransom-note
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 解法一:暴力

python 版

class Solution(object):
    def canConstruct(self, ransomNote, magazine):
        """
        :type ransomNote: str
        :type magazine: str
        :rtype: bool
        """
        m = list(magazine)
        r = list(ransomNote)
        for i in range(len(m)):
            if m[i] in r:
                r.remove(m[i])
        if len(r) == 0:
            return True
        else:
            return False

JS版

new RedExp()为正则表达式,RegExp 对象用于将文本与一个模式匹配。jie

/**
 * @param {string} ransomNote
 * @param {string} magazine
 * @return {boolean}
 */
var canConstruct = function(ransomNote, magazine) {
    for(let mg of magazine){
        if(ransomNote.includes(mg)){
            ransomNote = ransomNote.replace(new RegExp(mg),'')
        }
    }
    return ransomNote.length == 0
};

解法二:哈希解法

 题目只包含小写字母,可采用空间换取时间的哈希策略,用一个长度为26的数组记录magazine里面字母出现的次数

python 版

class Solution(object):
    def canConstruct(self, ransomNote, magazine):
        """
        :type ransomNote: str
        :type magazine: str
        :rtype: bool
        """
        # 使用数组作为哈希表
        arr = [0]*26
        for x in magazine:
            arr[ord(x)-ord('a')] += 1
        for x in ransomNote:
            if arr[ord(x) - ord('a')] == 0:
                return False
            else:
                arr[ord(x) - ord('a')] -= 1
        return True
class Solution(object):
    def canConstruct(self, ransomNote, magazine):
        """
        :type ransomNote: str
        :type magazine: str
        :rtype: bool
        """
        # 使用defaultdict
        from collections import defaultdict
        hashmap = defaultdict(int)
        for x in magazine:
            hashmap[x] += 1
        for x in ransomNote:
            value = hashmap.get(x)
            if value is None or value == 0:
                return False
            else:
                hashmap[x] -= 1
        return True
        
        # map
        hashmap = dict()
        for s in ransomNote:
            if s in hashmap:
                hashmap[s] += 1
            else:
                hashmap[s] = 1
        
        for l in magazine:
            if l in hashmap:
                hashmap[l] -= 1
        for key in hashmap:
            if hashmap[key]>0:
                return False
        return True
        
##########
        c1 = collections.Counter(ransomNote)
        c2 = collections.Counter(magazine)
        x = c1-c2
        # x只保留大于0的符号,当c1里面的符号个数小于c2时,不会被保留
        if (len(x)==0):
            return True
        else:
            return False

JS版

/**
 * @param {string} ransomNote
 * @param {string} magazine
 * @return {boolean}
 */
var canConstruct = function(ransomNote, magazine) {
    const arr = new Array(26).fill(0),base = 'a'.charCodeAt();
    for(const s of magazine){
        arr[s.charCodeAt()-base] += 1;
    }
    for(const s of ransomNote){
        const i = s.charCodeAt() - base;
        if(!arr[i]) return false;
        arr[i] -= 1;
    }
    return true
};

15.三数之和

 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

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

双指针法

python版

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        ans = []
        n = len(nums)
        nums.sort()
       #找出a+b+c=0
       # a=nums[i],b=nums[left],c=nums[right]
        for i in range(n):
            left = i+1
            right = n-1
        #    排序之后第一个元素大于零,永远凑不成三元组
            if nums[i]>0:
                break
            if i>=1 and nums[i] == nums[i-1]:#去重a
                continue
            while left<right:
                total = nums[i]+nums[left]+nums[right]
                if total>0:
                    right -= 1
                elif total<0:
                    left += 1
                else:
                    ans.append([nums[i],nums[left],nums[right]])
                    # 去重逻辑应该放在找到一个三元组之后,对b和c去重
                    while left != right and nums[left] == nums[left+1]: left+=1
                    while left != right and nums[right] == nums[right-1]:right-=1
                    left+=1
                    right-=1
        return ans


 JS版

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
    const res = [], len = nums.length
    // 将数组排序
    nums.sort((a, b) => a - b)
    for (let i = 0; i < len; i++) {
        let l = i + 1, r = len - 1, iNum = nums[i]
        // 数组排过序,如果第一个数大于0直接返回res
        if (iNum > 0) return res
        // 去重
        if (iNum == nums[i - 1]) continue
        while(l < r) {
            let lNum = nums[l], rNum = nums[r], threeSum = iNum + lNum + rNum
            // 三数之和小于0,则左指针向右移动
            if (threeSum < 0) l++ 
            else if (threeSum > 0) r--
            else {
                res.push([iNum, lNum, rNum])
                // 去重
                while(l < r && nums[l] == nums[l + 1]){
                    l++
                }
                while(l < r && nums[r] == nums[r - 1]) {
                    r--
                }
                l++
                r--
            }
        }
    }
    return res


};

18.四数之和

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

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

 解法一:双指针(同三数之和)python版本

class Solution(object):
    def fourSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        # 双指针
        nums.sort()
        n = len(nums)
        res = []
        for i in range(n):
            if i > 0 and nums[i] == nums[i-1]: continue
            for k in range(i+1,n):
                if k > i + 1 and nums[k] == nums[k-1]: continue
                p = k + 1
                q = n - 1
                while p < q:
                    if nums[i] + nums[k] + nums[p] + nums[q] > target: q -= 1
                    elif nums[i] + nums[k] + nums[p] + nums[q] < target : p += 1
                    else:
                        res.append([nums[i], nums[k], nums[p], nums[q]])
                        while p < q and nums[p] == nums[p+1]: p += 1
                        while p < q and nums[q] == nums[q-1]: q -= 1
                        p += 1
                        q -= 1
        return res

JS版本

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[][]}
 */
var fourSum = function(nums, target) {
    const len = nums.length;
    if(len < 4) return [];
    nums.sort((a, b) => a - b); // 升序排列
    const res = [];
    for(let i = 0; i < len - 3; i++) {
        // 去重i
        if(i > 0 && nums[i] === nums[i - 1]) continue;
        for(let j = i + 1; j < len -2; j++) {
            // 去重j
            if(j > i+1 && nums[j] === nums[j - 1]) continue;
            let l = j + 1, r = len - 1;
            while(l < r) {
                const sum = nums[i] + nums[j] + nums[l] + nums[r];
                if(sum < target) {l++; continue}
                if(sum > target) {r--; continue}
                res.push([nums[i],nums[j],nums[l],nums[r]]);
                // 去重 nums[r]与nums[l]
                while(l < r && nums[l] === nums[++l]);
                while(l < r && nums[r] === nums[--r]);
            }

        }
    }
    return res;
};

哈希表法python:

# 哈希表法
        hashmap = dict()
        for n in nums:
            if n in hashmap:
                hashmap[n] += 1
            else:
                hashmap[n] = 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 hashmap:
                        count = (nums[i] == val) + (nums[j] == val) + (nums[k] == val)
                        if hashmap[val] > count:
                            ans_tmp = tuple(sorted([nums[i],nums[j],nums[k],val]))
                            ans.add(ans_tmp)
                        else:
                            continue
        return list(ans)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值