LeetCode | Arrays & Hashing

217. Contains Duplicate | Easy

class Solution:
    def containDuplicate(self, nums):
        from collections import defaultdict

        hash = defaultdict(int)
        for num in nums:
            hash[num] += 1
            if hash[num] == 2:
                return True
        return False

    def containDuplicate2(self, nums):
        hash = set()
        for num in nums:
            if num in hash:
                return True
            hash.add(num)
        return False

242. Valid Anagram | Easy

  • 试了两版解决dict的key为空的情况,效果差不多
    • defaultdict(int)
    • get(key, 0)
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        from collections import defaultdict
        hash = defaultdict(int)

        if len(s) != len(t):
            return False

        for index in range(len(s)):
            hash[s[index]] += 1
            hash[t[index]] -= 1

        for key in hash:
            if hash[key] != 0:
                return False
        return True

    def isAnagram2(self, s: str, t: str) -> bool:
        hash = {}

        if len(s) != len(t):
            return False

        for index in range(len(s)):
            hash[s[index]] = hash.get(s[index], 0) + 1
            hash[t[index]] = hash.get(t[index], 0) - 1

        for key in hash:
            if hash[key] != 0:
                return False
        return True

1. Two Sum

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hash = {}

        for index in range(len(nums)):
            if nums[index] in hash.keys():
                return [hash[nums[index]], index]
            hash[target - nums[index]] = index
        return []

49. Group Anagrams | Medium

Version1

  • 一个非常直接的想法就是维护一个hashtable,key就是每个split的char,value就是对应的Item list;
  • Version1:记录一下错误
    1. list是Unhash type | 解决:sort()之后转tuple
class Solution:
    def groupAnagrams(self, strs: List[str]):
        hash = {}
        for item in strs:
            char_ls = []
            for char in item:
                char_ls.append(char)
            char_ls.sort()
            char_ls = tuple(char_ls)
            if char_ls not in hash:
                hash[char_ls] = []
            hash[char_ls].append(item)

        ans = []
        for key in hash:
            ans.append(hash[key])
        return ans

Version2

  • 看了一眼别人的代码2333,优化点记录!()
    1. 首先是sorted()sort()的区别
      • sort() function is very similar to sorted() but unlike sorted it returns nothing and makes changes to the original sequence. Moreover, sort() is a method of list class and can only be used with lists.
      • sorted() method sorts the given sequence as well as set and dictionary(which is not a sequence) either in ascending order or in descending order(does unicode comparison for string char by char) and always return the a sorted list. This method doesnot effect the original sequence.
    2. 其次是dic的value的返回不需要再用一层for循环得到!!
  • 记号: m为strs的长度,n为str中item的平均长度
    • 时间复杂度: O ( m n l o g n ) O(mnlogn) O(mnlogn)(ps:排序的 O ( n l o g n ) O(nlogn) O(nlogn),做了 m m m次)
class Solution:
	def groupAnagrams(self, strs: List[str]):
		hash = {}
		for item in strs:
			key = ''.join(sorted(s)) # 1. sorted返回list 要join拼接
			if key not in hash:
				dic[key] = []
			dic[key].append(item)
		return list(dic.values())  # 2. 

Version3

  • 参考neetcode滴!
  • 时间复杂度 O ( m n ) O(mn) O(mn)
  • 想法:大体思路是一样的都是维护一个hashmap,但是在key那做了优化;version2是对每个item sort之后存入key,version3则是维护一个长度为26的list,对应a,…,z(关键在于这个长度是26哈哈哈for一遍item还是可控的,实际上也是一种程度的有序了);
  • trick here:
    1. 只会输入26个小写字母,考虑key为tuple(array),其中array维护word的char统计信息,array的index表示26字母的位置,value就是次数;
    2. 为什么key用tuple?因为list不可以报错TypeError: unhashable type: 'list'
  • 几个可以学习的点:
    1. defaultdict()
    2. 获取相对位置!ord函数的运用;
    3. 同样的list unhashable的问题,转tuple;
    4. dict.values()
import collections
class Solution:
	def groupAnagrams(self, strs: List[str]):
		ans = collections.defaultdict(list)
		for item in strs:
			count = [0] * 26  # a,...,z
			for char in item:
				count[ord(char) - ord("a")] += 1
			ans[tuple(count)].append(item)
		return list(ans.values())

347. Top K Frequent Elements

Version1 | 失败

  • 总体思路:统计nums的各num的出现频次(hash dict保存);利用对value进行排序,取最大的k个,返回对应的key;
  • 失败的关键点在于在返回对应的key时,做了一个key-value的反转,但是没有考虑到value通常并不是唯一的,即多个key对应一个value无法进行正确的反转;如何返回对应的key呢?
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        ans = []
        hash = {}

        for num in nums:
            if num not in hash:
                hash[num] = 0
            hash[num] += 1

        re_hash = {}
        for key in hash:
            re_hash[hash[key]] = key
        
        tmp = sorted(list(hash.values()), reverse=True)
        print(re_hash, tmp)
        for i in tmp[:k]:
            ans.append(re_hash[i])
        return ans

Version2

  • 这里就是把利用对value进行排序,取最大的k个,返回对应的key这一步实现综合起来,打包成hash.items()
  • 回过头来再看一遍有个注意点:dict.values()要转list!!
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        hash = {}
        for num in nums:
            if num not in hash:
                hash[num] = 0
            hash[num] += 1
        tmp = sorted(list(hash.values()), reverse=True)
        return [key for key, val in hash.items() if val in tmp[: k]]

Version3

在这里插入图片描述

  • 还是neetcode!
  • 时间复杂度 O ( n ) O(n) O(n)(空间复杂度 O ( n ) O(n) O(n)
  • 看了一下他的思路,他的时间复杂度降下来是建立在不用排序的基础上的,重新开辟了个freq的list存储,index表示出现的频次,freq[index]存放出现Index次的nums,最后再从后往前找到k个就可以了;
  • 可以学习的点
    1. dict.get(key, default): 在 key(键)不在字典中时,可以返回默认值 None 或者设置的默认值;
    def topKFrequent2(self, nums: List[int], k: int) -> List[int]:
        # bucket sort
        hash = {}
        for n in nums:
            hash[n] = 1 + hash.get(n, 0)

        freq = [[] for _ in range(len(nums) + 1)]
        for key, val in hash.items():
            freq[val].append(key)

        res = []
        for i in range(len(freq) - 1, 0, -1):
            for n in freq[i]:
                res.append(n)
                if len(res) == k:
                    return res

238. Product of Array Except Self

奇怪了!!ver2明明是按ver3(nc)的思路来的,为什么跑出来时空性能差距这么大…?明天来看;

class Solution:
    def productExceptSelf(self, nums):
        from collections import defaultdict
        hash = defaultdict(int)
        res = []

        for num in nums:
            hash[num] += 1

        for num in nums:
            tmp = 1
            for k, v in hash.items():
                if k == num:
                    tmp = tmp * k ** (v - 1)
                if k != num:
                    tmp = tmp * k ** v
            res.append(tmp)
        return res

    def productExceptSelf2(self, nums):
        pre = [1]
        post = [1]
        for i in range(1, len(nums)):
            pre.append(pre[i - 1] * nums[i - 1])
            post.insert(0, post[0] * nums[len(nums) - i])
        return [pre[i] * post[i] for i in range(len(nums))]

    def productExceptSelf3(self, nums):
        res = [1] * (len(nums))

        prefix = 1
        for i in range(len(nums)):
            res[i] = prefix
            prefix *= nums[i]
        postfix = 1
        for i in range(len(nums) - 1, -1, -1):
            res[i] *= postfix
            postfix *= nums[i]
        return res

36. Valid Sudoku

今天先自己过一遍,明天再把nc的顺一遍从238开始;

  • 这道题主要是行列,小九宫格的处理
    • 二维不好切片列:[j[i] for j in board]用它取列了;
    • 小九宫格应该也可以去做简化的;
class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
    def isValidSudoku2(self, board: List[List[str]]) -> bool:
        from collections import defaultdict
        def check(array):
            count = defaultdict(int)
            for i in range(9):
                if array[i] == '.':
                    continue
                count[array[i]] += 1
                if count[array[i]] > 1:
                    return False
            return True

        for i in range(9):
            if not check(board[i]) or not check([j[i] for j in board]):
                return False

        for r in range(3):
            for c in range(3):
                tmp = []
                tmp.extend(board[3 * r][3 * c: 3 * c + 3])
                tmp.extend(board[3 * r + 1][3 * c: 3 * c + 3])
                tmp.extend(board[3 * r + 2][3 * c: 3 * c + 3])
                if not check(tmp):
                    return False
        return True

128. Longest Consecutive Sequence

  • 找起始的元素,去计算这个其实元素的连续串的长度,更新longest;
  • 不是起始元素continue掉;
class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        nums = set(nums)
        longest = 0
        for num in nums:
            if num - 1 in nums:
                continue

            lenth = 1
            while num + lenth in nums:
                lenth += 1
            longest = max(lenth, longest)
        return longest

271. Encode and Decode Strings

我楞是没看懂啥意思哈哈哈哈正常进来正常出来orz…
虽然我知道不能用split写哈哈哈哈哈哈哈哈哈,没有但是但是就是下面还是用split写了;

  • split这玩意要取[-1],他是相当于一双手,把分隔符:;两边拨开,所以最后出来一个空串需要删掉;
class Solution:
    def encode(self, strs):
        res = ''
        for str in strs:
            if str == ':':
                res = res + str + '::;'
                continue
            res = res + str + ':;'
        return res

    def decode(self, str):
        res = str.split(":;")[:-1]
        for i in range(len(res)):
            if res[i] == '::':
                res[i] = ':'
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值