文章目录
- 78. 子集(集合的所有子集)
- 90. 子集 II(集合的所有子集)
- 792. 匹配子序列的单词数(判断是否为子集)
- 500. 键盘行(集合的交集)
- 409. 最长回文串(set)
更多 leetcode 题解可参考:【Programming】
78. 子集(集合的所有子集)
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集
思路:可以迭代,可以回溯,
算 1 的子集的时候,新增 1 结合 空集;
算 2 的子集的时候,2 结合 1 的所有子集;
算 3 的子集的时候,3 结合 2 的所有子集
…
class Solution(object):def subsets(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""result = [[]]for i in nums:result.extend([j + [i] for j in result])return result
相似题目 1863. 找出所有子集的异或总和再求和
90. 子集 II(集合的所有子集)
给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
思路:和 78 唯一不同的是 nums 可能包含一样的元素,这个时候就会存在 [1,2] 和 [2,1] 或者更难一点的 [1,2,2] 和 [2,1,2] 的情况,78 的解法这两个都会保留(78中元素不一样),但是这题只能保留其中一种!
简单的 set 好像排除不了,我用的是 sorted
class Solution(object):def subsetsWithDup(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""result = [[]]for i in nums:result.extend([j + [i] for j in result])set1 = set(tuple(sorted(item)) for item in result) # tuple 才能 hash——set,sorted 配合set来去重list1 = list(list(item) for item in set1)# 转化成输出的格式return list1
792. 匹配子序列的单词数(判断是否为子集)
给定字符串 S 和单词字典 words, 求 words[i] 中是 S 的子序列的单词个数。
- 示例:
输入:
S = “abcde”
words = [“a”, “bb”, “acd”, “ace”]
输出: 3
解释: 有三个是 S 的子序列的单词: “a”, “acd”, “ace”。
注意:
所有在words和 S 里的单词都只由小写字母组成。
S 的长度在 [1, 50000]。
words 的长度在 [1, 5000]。
words[i]的长度在[1, 50]。
思路:in 或者 find 都不能判断这种跨越的子集,暴力法遍历了
class Solution(object):def numMatchingSubseq(self, S, words):""":type S: str:type words: List[str]:rtype: int"""count = 0for item in words:i = 0j = 0flag = 0while(i<len(S) and j<len(item)):if S[i] == item[j]:i+=1j+=1if j==len(item):breakelse:i+=1if i>len(item) and item[j] not in S: # 根本不在S中就不浪费表情去一个一个滑动找了breakif j == len(item):count+=1return count
但是超时了!字典树!
class Solution(object):def numMatchingSubseq(self, S, words):""":type S: str:type words: List[str]:rtype: int"""import collectionswaiting = collections.defaultdict(list)for w in words:waiting[w[0]].append(iter(w[1:]))for c in S:# print('c', c)# Python 字典 pop() 方法删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。# 把所有以c开头的word都删除for it in waiting.pop(c, ()):# 如果这个word还有其他字母,则与之前的合并,否则放到None中,表示该word能匹配waiting[next(it, None)].append(it)return len(waiting[None])
500. 键盘行(集合的交集)
给定一个单词列表,只返回可以使用在键盘同一行的字母打印出来的单词。键盘如下图所示。
-
示例:
输入: [“Hello”, “Alaska”, “Dad”, “Peace”]
输出: [“Alaska”, “Dad”] -
注意:
你可以重复使用键盘上同一字符。
你可以假设输入的字符串将只包含字母。
思路:暴力法,比较每一个字母是否在键盘的三行中
class Solution(object):def findWords(self, words):""":type words: List[str]:rtype: List[str]"""s1 = "qwertyuiop"s2 = "asdfghjkl"s3 = "zxcvbnm"result = []for word in words: # 遍历单词item = set(word.lower())num1 = 0num2 = 0num3 = 0for i in item:if i in s1:num1+=1elif i in s2:num2+=1else:num3+=1if num1==len(item) or num2==len(item) or num3==len(item):result.append(word)return result
还可以用集合的交集(和三行的交集是否为本身,是的话就表示该 string 是由一行键盘打出来的),这样就不用两层循环了!
class Solution(object):def findWords(self, words):""":type words: List[str]:rtype: List[str]"""s1 = "qwertyuiop"s2 = "asdfghjkl"s3 = "zxcvbnm"result = []for word in words: # 遍历单词if set(word.lower()) & set(s1) == set(word.lower()) or\set(word.lower()) & set(s2) == set(word.lower()) or \set(word.lower()) & set(s3) == set(word.lower()):result.append(word)return result
拓展,集合的并集 | 集合的差 -
409. 最长回文串(set)
给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。
在构造过程中,请注意区分大小写。比如 “Aa” 不能当做一个回文字符串。
-
注意:
假设字符串的长度不会超过 1010。 -
示例 1:
输入:
“abccccdd”
输出:
7 -
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
思路:先用 set 统计每个元素的数量,偶数的可以直接算作回文串的子集,奇数减1成偶数让其构成回文串子集(如果元素数量是1,减去后就为0)!最后输出结果,把子集拼起来,+1 即可,如果子集拼起来的长度和原字符串的长度相等,就不用加1了!
class Solution(object):def longestPalindrome(self, s):""":type s: str:rtype: int"""set1 = set(s)number_list = []sum1 = 0for i in set1: # 统计每个元素的数量number_list.append(s.count(i))for i,j in enumerate(number_list): # 遍历数量,偶数不变,奇数减一if j % 2 == 1:number_list[i] -= 1sum1 += number_list[i]if sum1+1 > len(s): # 这里避免,bb 的情况return len(s)else:return sum1+1