Python 实例教学_ 05_字典

Python 1-18 字典
哈希表 Hash table
Python collections.Counter
Python collections.defaultdict

第一课

1331. 数组序号转换

class Solution:
    def arrayRankTransform(self, arr: List[int]) -> List[int]:        
        d = {v:k+1 for k, v in enumerate(sorted(set(arr)))}        
        return [d[i] for i in arr]

1748. 唯一元素的和

class Solution:
    def sumOfUnique(self, nums: List[int]) -> int:
        d = {}
        for i in nums:
            d[i] = d.get(i, 0) + 1
        
        return sum(x for x in d if d[x] == 1)

389. 找不同

class Solution:
    def findTheDifference(self, s: str, t: str) -> str:
    	### 方法一:计数
        d = {}
        for c in s:
            d[c] = d.get(c, 0) + 1
        for c in t:
            d[c] = d.get(c, 0) - 1 
            if d[c] < 0: return c

		### 方法一:计数
        d = {}
        for c in s + t:
            d[c] = d.get(c, 0) + 1
        return [x for x in d if d[x]%2][-1]

		### 方法二:求和
        return chr(sum(ord(c) for c in t) - sum(ord(c) for c in s))
        # 利用 Counter (标准库的 collections)
        # return list(Counter(t) - Counter(s))[0]

**知识点:**chr,ord,map,reduce (functools 库),xor,ascii 码。
使用字符(注意不是字符串)异或运算 ^

  • 一个数和 0 做 XOR 运算等于本身:a⊕0 = a
  • 一个数和其本身做 XOR 运算等于 0:a⊕a = 0
  • XOR 运算满足交换律和结合律:a⊕b⊕a = (a⊕a)⊕b = 0⊕b = b
  • class Solution:
        def findTheDifference(self, s: str, t: str) -> str:
        	### 方法三:位运算
            res = 0
            for c in s + t:
                res ^= ord(c)        
            return chr(res)
    
            # return chr(reduce(xor, map(ord, s + t)))
    

    第二课

    2006. 差的绝对值为 K 的数对数目

    class Solution:
        def countKDifference(self, nums: List[int], k: int) -> int:
            '''
            res, n = 0, len(nums)        
            for i in range(n):
                for j in range(i+1, n):
                    if abs(nums[i]-nums[j]) == k:
                        res += 1
            return res
            '''
            res, d = 0, defaultdict(int)
            for i in nums:
                d[k+i] += 1
            for i in nums:          
                res += d[i]
    
            return res
    

    1880. 检查某单词是否等于两单词之和

    class Solution:
        def isSumEqual(self, firstWord: str, secondWord: str, targetWord: str) -> bool:
            # d = {'a':'0','b':'1','c':'2','d':'3','e':'4','f':'5','g':'6','h':'7','i':'8','j':'9'}
            # d[x], str(ord(x)-ord('a'))
    
            f = ''.join([str(ord(x)-97) for x in firstWord])
            s = ''.join([str(ord(x)-97) for x in secondWord])
            t = ''.join([str(ord(x)-97) for x in targetWord])
    
            return int(f) + int(s) == int(t)
    

    1897. 重新分配字符使所有字符串都相等

    class Solution:
        def makeEqual(self, words: List[str]) -> bool:
            d = defaultdict(int)
    
            for word in words:
                for w in word:
                    d[w] += 1
            for i in d:
                if d[i] % len(words): return False        
            
            return True
    

    第三课

    1365. 有多少小于当前数字的数字

    class Solution:
        def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:        
            x = sorted(nums)
            d = defaultdict(int)
            
            #for i, v in enumerate(x):
                #if v not in d:
                    #d[v] = i
                    
            for i in range(len(nums)-1, -1,-1):
                d[x[i]] = i
                
            return [d[i] for i in nums]
    

    1189. “气球” 的最大数量

    class Solution:
        def maxNumberOfBalloons(self, text: str) -> int:
            d = {c:0 for c in 'balon'}
            for c in text:
                if c in 'balon':
                    d[c] += 1
    
            return min(d[c]//2 if c in ['o', 'l'] else d[c] for c in d)        
    

    1002. 查找共用字符

    class Solution:
        def commonChars(self, words: List[str]) -> List[str]:
    	    # 以第一个单词为基准统计每一个字符数量,然后其它单词比较。
            d = defaultdict(int)
            res = []
            for c in words[0]:
                d[c] += 1
            
            for w in words[1:]:
                for c in d:
                    d[c] = min(d[c], w.count(c))
            
            for c in d:
                if d[c]:
                    res.extend(c*d[c])
            return res
    

    第四课

    914. 卡牌分组

    class Solution:
        def hasGroupsSizeX(self, deck: List[int]) -> bool:
            
            d = defaultdict(int)
            for i in deck:
                d[i] += 1
            x = min(d.values())
            #if x == 1:return False
            
            for i in range(2, x+1):
                for j in d.values():
                    if j % i:
                        break
                else:    
                    return True
                    
            return False
    

    136. 只出现一次的数字

    class Solution:
        def singleNumber(self, nums: List[int]) -> int:
    		## 方法一:dict 计数
            d = {}
            for i in nums: d[i] = d.get(i, 0) + 1            
            return [x for x in d if d[x] == 1][0]
    
    		## 方法二:Counter
            count = Counter(nums)
            for i in count:
                if count[i] == 1: return i        
            ## 方法三:
            return sum(set(nums))*2-sum(nums) 
    

    846. 一手顺子

    class Solution:
        def isNStraightHand(self, hand: List[int], groupSize: int) -> bool:
            if len(hand) % groupSize: return False
            hand.sort()
            cnt = Counter(hand)
            for h in hand:
                if cnt[h] == 0: continue
                for num in range(h, h + groupSize):
                    if cnt[num] == 0: return False
                    cnt[num] -= 1                
            return True
    

    第五课

    1773. 统计匹配检索规则的物品数量

    class Solution:
        def countMatches(self, items: List[List[str]], ruleKey: str, ruleValue: str) -> int:
            ans = 0
            for item in items:
                if ruleKey == 'type': 
                    if ruleValue == item[0]: ans += 1
                elif ruleKey == 'color': 
                    if ruleValue == item[1]: ans += 1
                elif ruleKey == 'name': 
                    if ruleValue == item[2]: ans += 1
            return ans
    
            # ans = 0
            # d = {"type":0, "color":1, "name":2}  # 影射
            # for item in items:
            #     if item[d[ruleKey]] == ruleValue:
            #         ans += 1
            # return ans
            # idx = {"type":0, "color":1, "name":2}[ruleKey]
            # return sum(item[idx] == ruleValue for item in items)
    

    ★1. 两数之和

    不能排序,因为找的是索引。

    class Solution:
        def twoSum(self, nums: List[int], target: int) -> List[int]:
        	# # 方法一:暴力解法
    		# # 枚举数组中的每一个数 x,在 x 后面的元素中寻找 target - x。
            # for i, x in enumerate(nums):
            #     for j, y in enumerate(nums[i+1:]): # 从 i 后面找
            #         if x + y == target:
            #             return [i, i+1 + j]
            # return []
    
    		# ## 方法二:index
            # for i, x in enumerate(nums):
            #     if target - x in nums[i+1:]:
            #        return [i, nums.index(target - x, i + 1)]            
            #     # try:
            #     # 	j = nums.index(target - element, i + 1)
            #     # 	return i, j
            #     # except: pass
    
    		## 方法三:哈希表
    		# 创建一个字典,对于每一个 x,首先查询哈希表中是否存在 target - x,如果存在,则返回结果,否则将 x 插入到哈希表中。
    		# 注意:方法一是对于 x,从后面找 target - x;方法二是先把 target - x 和它的下标放到字典中,然后对后面的 x 在字典中找 target - x。
            hashtable = dict()
            for j, y in enumerate(nums):
                x = target - y
                if x in hashtable:
                    return [hashtable[x], j]
                hashtable[y] = j            
            return []
    

    645. 错误的集合

    class Solution:
        def findErrorNums(self, nums: List[int]) -> List[int]:
            c = Counter(nums)
            for i in range(1, len(nums) + 1):
                if i not in c: y = i
                if c[i] == 2: x = i
            return [x, y]
    

    第六课

    884. 两句话中的不常见单词

    class Solution:
        def uncommonFromSentences(self, s1: str, s2: str) -> List[str]:
            c = Counter(s1.split() + s2.split())
            return [k for k, v in c.items() if v == 1]
    

    290. 单词规律

    class Solution:
        def wordPattern(self, pattern: str, s: str) -> bool:
            words = s.split()
            d = {}
            if len(words) != len(pattern):return False
            # for i, c in enumerate(pattern):
            #     w = words[i]
            for c, w in zip(pattern, words):
                if c not in d: d[c] = w
                elif d[c] != w: return False
                    
            return len(d) == len(set(words))
    

    1160. 拼写单词

    class Solution:
        def countCharacters(self, words: List[str], chars: str) -> int:
            d = {}
            res = 0        
            for c in chars:
                d[c] = d.get(c, 0) + 1          
                          
            for w in words:
                x = d.copy()
                for c in w:
                    if c not in d or x[c] == 0: break
                    else:x[c] -= 1
                else: res += len(w)
                    
            return res
    

    练习题

    1748. 唯一元素的和

    class Solution:
        def sumOfUnique(self, nums: List[int]) -> int:
            cnt = Counter(nums)
            return sum(k for k, v in cnt.items() if v == 1)
    

    347. 前 K 个高频元素

    class Solution:
        def topKFrequent(self, nums: List[int], k: int) -> List[int]:
            d = {}
            for x in nums:
                d[x] = d.get(x, 0) + 1        
    
            d = defaultdict(int)
            for x in nums:
                d[x] += 1
    
            return sorted(d, key=lambda y:d[x], reverse=True)[:k]
    
            cnt = Counter(nums)
            return sorted(cnt, key=lambda x:-cnt[x])[:k]
    
            return sorted(cnt := Counter(nums), key=lambda x:-cnt[x])[:k]
    

    1399. 统计最大组的数目

    class Solution:
        def countLargestGroup(self, n: int) -> int:
            d = defaultdict(int)
            for i in range(1, n + 1):
                # dp = sum(int(x) for x in str(i))
                # dp = sum(map(int, str(i)))
    
                dp = 0
                while i:
                    # i, r = divmod(i, 10)
                    i, r = i // 10, i % 10
                    dp += r
    
                d[dp] += 1
    
            ans, mx = 1, 0
            for x in d.values():
                if x > mx:
                    mx = x
                    ans = 1
                elif x == mx:
                    ans += 1
            return ans
                
            # mx = max(d.values())
            # return sum(mx == v for v in d.values())
    

    2363. 合并相似的物品

    class Solution:
        def mergeSimilarItems(self, items1: List[List[int]], items2: List[List[int]]) -> List[List[int]]:
            d = defaultdict(int)
            for v, w in items1 + items2:
                d[v] += w
            
            return sorted(d.items())
    

    1941. 检查是否所有字符出现次数相同

    class Solution:
        def areOccurrencesEqual(self, s: str) -> bool:
    
            # d = defaultdict(int)
            # for c in s:
            #     d[c] += 1
            
            d = Counter(s)
    
            res = d[s[0]]
            for v in d.values():
                if v != res: return False
            return True        
            return len(set(Counter(s).values())) == 1
    

    2399. 检查相同字母间的距离

    class Solution:
        def checkDistances(self, s: str, distance: List[int]) -> bool:
            d = {}
            for i, c in enumerate(s):
                x = ord(c) - ord('a')
                if x in d and i - d[x] - 1 != distance[x]: return False
                d[x] = i
            return True
    

    811. 子域名访问计数

    class Solution:
        def subdomainVisits(self, cpdomains: List[str]) -> List[str]:
            cnt = Counter()
            for cpdomain in cpdomains:
                x, domain = cpdomain.split()
                x = int(x)
                cnt[domain] += x
    
            #     for _ in range(domain.count('.')):
            #         _, domain = domain.split('.', 1)
            #         cnt[domain] += x
            # return [str(v) + ' ' + k for k, v in cnt.items()]
    
                while '.' in domain:
                    domain = domain[domain.index('.') + 1:]
                    cnt[domain] += x
           return [f"{v} {k}" for k, v in cnt.items()]
    

    2053. 数组中第 K 个独一无二的字符串

    class Solution:
        def kthDistinct(self, arr: List[str], k: int) -> str:
            d = Counter(arr)
            for i, s in enumerate(arr):
                if d[s] == 1:
                    k -= 1
                    if k == 0:
                        return s
            return ''
    

    2423. 删除字符使频率相同

    class Solution:
        def equalFrequency(self, word: str) -> bool:              
            # 同 1224
            a, b = defaultdict(int), defaultdict(int)       
            ans = 0
            n = len(word)
            for i, x in enumerate(word):
                a[x] += 1
                b[a[x]] += 1
                if a[x] * b[a[x]] == i + 1 and i != n-1: # 频率相等
                    ans = i + 2
                
                if a[x] * b[a[x]] == i: # 特判频率为 1,2 的情况
                    ans = i + 1
            
            return ans == n
           
            d = Counter(word)
            for c in d:
                d[c] -= 1
                s = {v for v in d.values() if v}
                if len(s) == 1: return True
                d[c] += 1
            return False
    

    2404. 出现最频繁的偶数元素

    class Solution:
        def mostFrequentEven(self, nums: List[int]) -> int:
            d = defaultdict(int)
            for x in nums:
                if x % 2 == 0: d[x] += 1
            arr = sorted(d.items(), key=lambda item:(-item[1], item[0]))
            return arr[0][0] if arr else -1
    

    作者:Yake1965

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python 05 Dict

    发表回复