leetcode刷题——哈希表

哈希表涉及leetcode问题:

  • 1 Two Sum (Easy)
  • 217 Contains Duplicate (Easy)
  • 594 Longest Harmonious Subsequence (Easy)
  • 128 Longest Consecutive Sequence (Hard)
  • 349 两个数组的交集(easy)
  • 350 两个数组的交集 II(easy)
  • 242 有效的字母异位词(easy)
  • 202 快乐数(easy)
  • 205 同构字符串(easy)
  • 451 根据字符出现频率排序(medium)
  • 15 三数之和(medium)
  • 18 四数之和(medium)
  • 454 四数相加 II(medium)
  • 49 字母异位词分组(medium)
  • 447 回旋镖的数量(easy)
  • 149 直线上最多的点数(hard)
  • 219 存在重复元素 II(easy)
  • 220 存在重复元素 III(medium)

哈希表问题

1. Two Sum (Easy)

https://leetcode-cn.com/problems/two-sum/

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        if not nums: return []
        #由于需要返回坐标,因此采用字典形式的hashmap
        hash_map = {}
        for i in range(len(nums)):
            t = target - nums[i]
            if t not in hash_map:
                hash_map[nums[i]] = i
            else:
                return [i, hash_map[t]]

217. Contains Duplicate (Easy)

https://leetcode-cn.com/problems/contains-duplicate/

class Solution:
    def containsDuplicate(self, nums: List[int]) -> bool:
        if not nums: return False
        if len(nums)<2:return False
        hash_map = set()
        for num in nums:
            if num not in hash_map:
                hash_map.add(num)
            else:
                return True
        return False

594. Longest Harmonious Subsequence (Easy)

https://leetcode-cn.com/problems/longest-harmonious-subsequence/

class Solution:
    def findLHS(self, nums: List[int]) -> int:
        '''
        暴力法,设置flag解决{1,1,1,1}这样的例子
        这道题,先排序,会省很多重复计算
        '''
        if not nums: return 0
        if len(nums)<2: return 0
        res = []
        for i in range(len(nums)):
            a  = 0
            flag = False
            for j in range(len(nums)):
                if nums[j] - nums[i] == 1:
                    a += 1
                    flag = True
                elif nums[j] == nums[i]:
                    a += 1
            if flag:
                res.append(a)
            else:
                res.append(0)
        # print(res)
        return max(res)
class Solution:
    def findLHS(self, nums: List[int]) -> int:
        '''
        hashmap hash表存储每个字符出现的次数
        '''
        if not nums: return 0
        if len(nums)<2: return 0

        hashmap = dict()
        for num in nums:
            hashmap[num] = hashmap.get(num, 0) + 1
        # print(hashmap)
        res = 0 
        for k, v in hashmap.items():
            if hashmap.get(k+1, 0) != 0:
                res = max(res, hashmap.get(k+1)+v)
        return res

128. Longest Consecutive Sequence (Hard)

https://leetcode-cn.com/problems/longest-consecutive-sequence/

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        '''
        暴力法(超时)复杂度为o(n3)
        '''
        if not nums: return 0
        max_len = 0
        for i in range(len(nums)):
            leng = 1
            cur = nums[i]
            while cur + 1 in nums:
                cur += 1
                leng += 1
            max_len = max(leng, max_len)
        return max_len           
class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        '''
        简单hashmap,时间复杂度为o(n2),accept但是依然不满足条件
        '''
        if not nums: return 0
        max_len = 0
        hashmap = set(nums)
        for i in range(len(nums)):
            leng = 1
            cur = nums[i]
            while cur + 1 in hashmap:
                cur += 1
                leng += 1
            max_len = max(leng, max_len)
        return max_len           
class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        '''
        hashmap进一步优化,去除重复计算时间复杂度o(n)
        '''
        if not nums: return 0
        max_len = 0
        hashmap = set(nums)
        for i in range(len(nums)):
            #找到一个合适的开头,如果nums[i]-1存在于hashmap中,那么这个元素就不能作为序列的起点
            if nums[i]-1 not in hashmap:
                leng = 1
                cur = nums[i]
                while cur + 1 in hashmap:
                    cur += 1
                    leng += 1
                max_len = max(leng, max_len)
        return max_len

349. 两个数组的交集(easy)

https://leetcode-cn.com/problems/intersection-of-two-arrays/

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:

        if not nums1 or not nums2: return []
        res = []
        hashmap1 = set(nums1)
        hashmap2 = set(nums2)
        for num in hashmap1:
            if num in hashmap2:
                res.append(num)
        
        return res

350. 两个数组的交集 II(easy)

https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/

class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        if not nums1 or not nums2: return []
        hashmap1 = dict.fromkeys(nums1, 0)
        hashmap2 = dict.fromkeys(nums2, 0)

        for num in nums1:
            hashmap1[num] += 1

        for num in nums2:
            if hashmap1.get(num) and hashmap1[num]>0:
                hashmap2[num] += 1
                hashmap1[num] -= 1
        # print(hashmap2)
        res = []
        for k, v in hashmap2.items():
            for _ in range(v):
                res.append(k)
        return res

242. 有效的字母异位词(easy)

https://leetcode-cn.com/problems/valid-anagram/

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        '''
        简单采用hashmap
        '''
        if not s and not t: return True
        if not s or not t: return False
        hashmap1 = dict.fromkeys(s, 0)
        hashmap2 = dict.fromkeys(t, 0)
        for char in s:
            hashmap1[char] += 1
        for char in t:
            hashmap2[char] +=1
        if hashmap1 == hashmap2:
            return True
        else:
            return False

202. 快乐数(easy)

https://leetcode-cn.com/problems/happy-number/

class Solution:
    def isHappy(self, n: int) -> bool:
        '''
        利用hashmap存储已经访问过的值,判断循环
        '''

        if n == 1: return True

        visited = set()
        while True:
            if n  == 1: return True
            elif n in visited: return False
            visited.add(n)
            n = sum([int(num)**2 for num in str(n)])

205. 同构字符串(easy)

https://leetcode-cn.com/problems/isomorphic-strings/

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:

        if not s and not t: return True
        if not s or not t: return False
        if len(s) != len(t): return False
        hashmap = dict()

        for i in range(len(s)):
            if hashmap.get(s[i]):
                #一对多
                if t[i] != hashmap[s[i]]:
                    return False
            hashmap[s[i]] = t[i]
        hashset = set(list(hashmap.values()))
        
        #多对一
        if len(hashset) == len(list(hashmap.keys())):
            return True
        else:
            return False

451. 根据字符出现频率排序(medium)

https://leetcode-cn.com/problems/sort-characters-by-frequency/

class Solution:
    def frequencySort(self, s: str) -> str:
        if not s: return ''

        hashmap = dict.fromkeys(s, 0)
        for char in s:
            hashmap[char] += 1
        # print(hashmap)
        tuple_ = sorted(hashmap.items(), key = lambda kv:(kv[1], kv[0]),reverse=True)
        # print(tuple_)
        res = []
        for k , v in tuple_:
            for _ in range(v):
                res.append(k)
        return ''.join(res)

15. 三数之和(medium)

https://leetcode-cn.com/problems/3sum/

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        '''
        two sum的做法,实际就是在nums[i+1:],求解target为-nums[i]的two sum
        '''
        if not nums: return []
        if len(nums)<3: return []
        res = set()
        nums.sort()
        if nums[0] > 0 or nums[-1]<0: return []

        for i in range(len(nums)-2):
            if i>0 and nums[i-1] == nums[i]: continue
            if nums[i] >0: break
            target = - nums[i]
            hashset = set()
            for j in range(i+1, len(nums)):
                t = target - nums[j]
                if t not in hashset:
                    hashset.add(nums[j])
                    continue
                triplet = [nums[i], t, nums[j]]
                triplet.sort()
                if tuple(triplet) not in res:
                    res.add(tuple(triplet))
        return [list(num) for num in res ]
  • 注意:这道题排序后采用对撞指针更加简单。利用对撞指针寻找和为-nums[i]的两个数

18. 四数之和(medium)

https://leetcode-cn.com/problems/4sum/

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        if not nums or len(nums)<4: return []

        nums.sort()
        res = []
        for i in range(len(nums)-3):
            if i>0 and nums[i]==nums[i-1]: continue
            for j in range(i+1, len(nums)-2):
                if j>i+1 and nums[j]==nums[j-1]:continue
                t = target - nums[j]- nums[i]

                ## two sum
                hashset = set()
                for k in range(j+1,  len(nums)):
                    t1 = t - nums[k]
                    lets = [nums[i], nums[j], nums[k], t1]
                    if t1 in hashset and lets not in res:
                        res.append(lets)
                    hashset.add(nums[k])
        return res
  • 注意:同样可以采用对撞指针求two sum,这道题的思路依然是转换成two sum

454. 四数相加 II(medium)

https://leetcode-cn.com/problems/4sum-ii/

class Solution:
    def fourSumCount(self, A: List[int], B: List[int], C: List[int], D: List[int]) -> int:
        '''
        将2个数之和作为键值,将o(n4)的复杂度降至o(n2)
        '''
        N = len(A)
        hashmap1 = {}
        hashmap2 = {}
        res = 0
        for num1 in A:
            for num2 in B:
                hashmap1[num1+num2] = hashmap1.get(num1+num2, 0) + 1
        
        for num1 in C:
            for num2 in D:
                hashmap2[num1+num2] = hashmap2.get(num1+num2, 0) + 1

        for k ,v in hashmap1.items():
            res += hashmap2.get(0-k, 0) * v
        return res

49. 字母异位词分组(medium)

https://leetcode-cn.com/problems/group-anagrams/

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:

        if not strs: return []
        from collections import defaultdict
        hashmap = defaultdict(list)
        hashmap1 = {}
        for i in range(len(strs)):
            for j in range(ord('a'),ord('z')+1):
                hashmap1[chr(j)] = 0

            for k in range(len(strs[i])):
                hashmap1[strs[i][k]] += 1

            hashmap[tuple(hashmap1.values())].append(strs[i])
        # print(hashmap)
        return list(hashmap.values())

447. 回旋镖的数量(easy)

https://leetcode-cn.com/problems/number-of-boomerangs/

class Solution:
    def numberOfBoomerangs(self, points: List[List[int]]) -> int:
        if not points or len(points)<3: return 0

        res = 0
        for i in range(len(points)):
            hashmap = dict()
            for j in range(len(points)):
                dist = (points[i][0] - points[j][0])**2 + (points[i][1] - points[j][1])**2
                hashmap[dist] = hashmap.get(dist, 0) + 1
            # print(hashmap)
            for v in hashmap.values():
                if v > 1:
                    res += v*(v-1)
        return res

149. 直线上最多的点数(hard)

https://leetcode-cn.com/problems/max-points-on-a-line/

  • 利用斜率来判定点共线(解题代码来自leetcode题解区powcai大佬,如果直接用除法计算容易出现截断从而出现错误。用公约数更好,如果直接调用math库里的gcd
    这个库里的gcd只能计算出正值,如果math.gcd(3,-6)得到3,因此大佬重新写了gcd,可以参考
class Solution:
    def maxPoints(self, points: List[List[int]]) -> int:
        from collections import Counter, defaultdict
        # 所有点统计
        points_dict = Counter(tuple(point) for point in points)
        # 把唯一点列举出来
        not_repeat_points = list(points_dict.keys())
        n = len(not_repeat_points)
        if n == 1: return points_dict[not_repeat_points[0]]
        res = 0
        # 求最大公约数
        def gcd(x, y):
            if y == 0:
                return x
            else:
                return gcd(y, x % y)

        for i in range(n - 1):
            # 点1
            x1, y1 = not_repeat_points[i][0], not_repeat_points[i][1]
            # 斜率
            slope = defaultdict(int)
            for j in range(i + 1, n):
                # 点2
                x2, y2 = not_repeat_points[j][0], not_repeat_points[j][1]
                dy, dx = y2 - y1, x2 - x1
                # 方式一 利用公约数
                g = gcd(dy, dx)
                if g != 0:
                    dy //= g
                    dx //= g
                slope["{}/{}".format(dy, dx)] += points_dict[not_repeat_points[j]]
            res = max(res, max(slope.values()) + points_dict[not_repeat_points[i]])
        return res

219. 存在重复元素 II(easy)

https://leetcode-cn.com/problems/contains-duplicate-ii/

class Solution:
    def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:

        if not nums: return False

        hashset = set()
        for i in range(len(nums)):
            # print(hashset)
            if nums[i] in hashset:
                return True
            hashset.add(nums[i])
            if len(hashset)>k:
                hashset.remove(nums[i-k])
            
        return False

220. 存在重复元素 III(medium)

https://leetcode-cn.com/problems/contains-duplicate-iii/

class Solution:
    def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:

        if not nums: return False
        hashset = set()
        for i in range(len(nums)):
            if t==0 and nums[i] in hashset:
                return True 
            elif t !=0:
                for num in hashset:
                    if abs(nums[i]-num) <=t:
                        return True
            hashset.add(nums[i])
            if len(hashset) > k:
                hashset.remove(nums[i-k])
        return False

跳转至标签分类页

你可能感兴趣的:(leetcode刷题)