接着上篇lintcode刷题笔记(一),继续刷题lintcode,练速度。。
(六)深度优先搜索(DFS, Deepth First Search)
680. Split String
Description
给一个字符串,你可以选择在一个字符或两个相邻字符之后拆分字符串,使字符串由仅一个字符或两个字符组成,输出所有可能的结果
Example
样例1
输入: "123"
输出: [["1","2","3"],["12","3"],["1","23"]]
样例2
输入: "12345"
输出: [["1","23","45"],["12","3","45"],["12","34","5"],["1","2","3","45"],["1","2","34","5"],["1","23","4","5"]
#coding:utf-8 """ Description Give a string, you can choose to split the string after one character or two adjacent characters, and make the string to be composed of only one character or two characters. Output all possible results. Example1 Input: "123" Output: [["1","2","3"],["12","3"],["1","23"]] Example2 Input: "12345" Output: [["1","23","45"],["12","3","45"],["12","34","5"],["1","2","3","45"],["1","2","34","5"],["1","23","4","5" """ class Solution: """ @param: : a string to be split @return: all possible split string array """ def splitString(self, s): # write your code here ret= [] if len(s)==0: return [[]] self.helper(s,0,ret) return ret def helper(self,s,start,ret,temp=[]): import copy if start==len(s): ret.append(copy.deepcopy(temp)) return if start<len(s): temp.append(s[start:start+1]) self.helper(s,start+1,ret,temp) temp.pop() if start+1<len(s): temp.append(s[start:start+2]) self.helper(s,start+2,ret,temp) temp.pop() if __name__=="__main__": s = Solution() print(s.splitString("123")) print(s.splitString("12345"))
136.Palindrome Partitioning
Description
给定字符串 s
, 需要将它分割成一些子串, 使得每个子串都是回文串.
返回所有可能的分割方案.
- 不同的方案之间的顺序可以是任意的.
- 一种分割方案中的每个子串都必须是
s
中连续的一段.
Example
样例 1:
输入: "a"
输出: [["a"]]
解释: 字符串里只有一个字符, 也就只有一种分割方式 (就是它本身)
样例 2:
输入: "aab"
输出: [["aa", "b"], ["a", "a", "b"]]
解释: 有两种分割的方式.
1. 将 "aab" 分割成 "aa" 和 "b", 它们都是回文的.
2. 将 "aab" 分割成 "a", "a" 和 "b", 它们全都是回文的.
#coding:utf-8 """ 136.Palindrome Partitioning Description Given a string s. Partition s such that every substring in the partition is a palindrome. Return all possible palindrome partitioning of s. Different partitionings can be in any order. Each substring must be a continuous segment of s. Example 1: Input: "a" Output: [["a"]] Explanation: Only 1 char in the string, only 1 way to split it (itself). Example 2: Input: "aab" Output: [["aa", "b"], ["a", "a", "b"]] Explanation: There are 2 ways to split "aab". 1. Split "aab" into "aa" and "b", both palindrome. 2. Split "aab" into "a", "a", and "b", all palindrome. """ class Solution: """ @param: s: A string @return: A list of lists of string """ def partition(self, s): # write your code here if len(s)==0: return [[]] ret=[] self.dfs(s,ret) return ret def dfs(self,s,ret,temp=[]): import copy if len(s)==0: ret.append(copy.deepcopy(temp)) return for i in range(len(s)): sub = s[0:i+1] if self.check(sub): temp.append(sub) self.dfs(s[i+1:],ret,temp) temp.pop() def check(self,sub): i,j=0,len(sub)-1 while i<j: if sub[i]==sub[j]: i+=1 j-=1 else: return False return True if __name__=="__main__": s =Solution() print(s.partition("aab")) print(s.partition("a"))
153. Combination Sum II
Description
给定一个数组 num
和一个整数 target
. 找到 num
中所有的数字之和为 target
的组合.
- 在同一个组合中,
num
中的每一个数字仅能被使用一次. - 所有数值 (包括
target
) 都是正整数. - 返回的每一个组合内的数字必须是非降序的.
- 返回的所有组合之间可以是任意顺序.
- 解集不能包含重复的组合.
Example
样例 1:
输入: num = [7,1,2,5,1,6,10], target = 8
输出: [[1,1,6],[1,2,5],[1,7],[2,6]]
样例 2:
输入: num = [1,1,1], target = 2
输出: [[1,1]]
解释: 解集不能包含重复的组合
#coding:utf-8 """ 153. Combination Sum II Description Given an array num and a number target. Find all unique combinations in num where the numbers sum to target. Each number in num can only be used once in one combination. All numbers (including target) will be positive integers. Numbers in a combination a1, a2, … , ak must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak) Different combinations can be in any order. The solution set must not contain duplicate combinations. Example 1: Input: num = [7,1,2,5,1,6,10], target = 8 Output: [[1,1,6],[1,2,5],[1,7],[2,6]] Example 2: Input: num = [1,1,1], target = 2 Output: [[1,1]] Explanation: The solution set must not contain duplicate combinations. """ class Solution: """ @param num: Given the candidate numbers @param target: Given the target number @return: All the combinations that sum to target """ def combinationSum2(self, num, target): # write your code here if len(num)==0: return [] ret=[] self.dfs(num,0,target,ret) return ret def dfs(self,num,i,target,ret,temp=[]): if target==0: sort_temp=sorted(temp) if sort_temp not in ret: ret.append(sort_temp) return if target<0: return if i==len(num): return while i<len(num): temp.append(num[i]) self.dfs(num,i+1,target-num[i],ret,temp) temp.pop() i+=1 if __name__=="__main__": s=Solution() print(s.combinationSum2(num = [7,1,2,5,1,6,10], target = 8)) print(s.combinationSum2(num = [1,1,1], target = 2)) print(s.combinationSum2(num = [2,3,6,7], target = 7))
152. Combinations
Description
给定两个整数 n
和 k
. 返回从 1, 2, ... , n
中选出 k
个数的所有可能的组合.
你可以以任意顺序返回所有的组合, 但是一个组合内的所有数字需要是升序排列的.
Example
样例 1:
输入: n = 4, k = 2
输出: [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
样例 2:
输入: n = 4, k = 1
输出: [[1],[2],[3],[4]]
#coding:utf-8 """ 152. Combinations Description Given two integers n and k. Return all possible combinations of k numbers out of 1, 2, ... , n. You can return all combinations in any order, but numbers in a combination should be in ascending order. Example 1: Input: n = 4, k = 2 Output: [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]] Example 2: Input: n = 4, k = 1 Output: [[1],[2],[3],[4]] """ class Solution: """ @param n: Given the range of numbers @param k: Given the numbers of combinations @return: All the combinations of k numbers out of 1..n """ def combine(self, n, k): # write your code here if n==0 and k!=0: return [] ret=[] self.dfs(n,1,k,ret) return ret def dfs(self,n,i,k,ret,temp=[]): import copy if k==0: ret.append(copy.deepcopy(temp)) return if i>n: return while i<=n: temp.append(i) self.dfs(n,i+1,k-1,ret,temp) temp.pop() i+=1 if __name__=="__main__": s=Solution() print(s.combine(n = 4, k = 2)) print(s.combine(n = 4, k = 1))
Description
给定一个候选数字的集合 candidates
和一个目标值 target
. 找到 candidates
中所有的和为 target
的组合.
在同一个组合中, candidates
中的某个数字不限次数地出现.
- 所有数值 (包括
target
) 都是正整数. - 返回的每一个组合内的数字必须是非降序的.
- 返回的所有组合之间可以是任意顺序.
- 解集不能包含重复的组合.
Example
样例 1:
输入: candidates = [2, 3, 6, 7], target = 7
输出: [[7], [2, 2, 3]]
样例 2:
输入: candidates = [1], target = 3
输出: [[1, 1, 1]]
#coding:utf-8 """ 135. Combination Sum Description Given a set of candidtate numbers candidates and a target number target. Find all unique combinations in candidates where the numbers sums to target. The same repeated number may be chosen from candidates unlimited number of times. All numbers (including target) will be positive integers. Numbers in a combination a1, a2, … , ak must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak) Different combinations can be in any order. The solution set must not contain duplicate combinations. Example 1: Input: candidates = [2, 3, 6, 7], target = 7 Output: [[7], [2, 2, 3]] Example 2: Input: candidates = [1], target = 3 Output: [[1, 1, 1]] """ #参考:https://leetcode-cn.com/problems/combination-sum/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-2/ class Solution: """ @param candidates: A list of integers @param target: An integer @return: A list of lists of integers """ def combinationSum(self, candidates, target): # write your code here size = len(candidates) if size==0: return [] candidates.sort() #排序保证最后数组按序排列 ret=[] self.dfs(candidates,0,size,target,ret) return ret def dfs(self,candidates,begin,size,target,ret,temp=[]): if target==0: if temp not in ret: ret.append(temp[:]) return if target<0: return for i in range(begin,size): temp.append(candidates[i]) self.dfs(candidates,i,size,target-candidates[i],ret,temp) #从i开始往后选下一个数据,保证避免出现重复 temp.pop()
18. Subsets II
Description
给定一个可能具有重复数字的列表,返回其所有可能的子集。
- 子集中的每个元素都是非降序的
- 两个子集间的顺序是无关紧要的
- 解集中不能包含重复子集
Example
样例 1:
输入:[0]
输出:
[
[],
[0]
]
样例 2:
输入:[1,2,2]
输出:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
Challenge
你可以同时用递归与非递归的方式解决么?
#coding:utf-8 """ 18. Subsets II Description Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set). Each element in a subset must be in non-descending order. The ordering between two subsets is free. The solution set must not contain duplicate subsets. Example 1: Input: [0] Output: [ [], [0] ] Example 2: Input: [1,2,2] Output: [ [2], [1], [1,2,2], [2,2], [1,2], [] ] Challenge Can you do it in both recursively and iteratively? """ class Solution: """ @param nums: A set of numbers. @return: A list of lists. All valid subsets. """ def subsetsWithDup(self, nums): # write your code here size=len(nums) if size==0: return [[]] nums.sort() ret=[] self.dfs(nums,0,size,ret) return ret def dfs(self,nums,begin,size,ret,temp=[]): if temp not in ret: ret.append(temp[:]) if begin==size: return for i in range(begin,size): temp.append(nums[i]) self.dfs(nums,i+1,size,ret,temp) temp.pop()
17. Subsets
Description
给定一个含不同整数的集合,返回其所有的子集。
子集中的元素排列必须是非降序的,解集必须不包含重复的子集。
Example
样例 1:
输入:[0]
输出:
[
[],
[0]
]
样例 2:
输入:[1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
Challenge
你可以同时用递归与非递归的方式解决么?
#coding:utf-8 """ 17. Subsets Description Given a set of distinct integers, return all possible subsets. Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. Example 1: Input: [0] Output: [ [], [0] ] Example 2: Input: [1,2,3] Output: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ] Challenge Can you do it in both recursively and iteratively? """ #方法一:递归公式 class Solution: """ @param nums: A set of numbers @return: A list of lists """ def subsets(self, nums): # write your code here size=len(nums) if size==0: return [[]] nums.sort() return self.help(nums,size) def help(self,nums,n): if n==1: return [[],[nums[0]]] ret = self.help(nums,n-1) for i in range(len(ret)): ret.append(ret[i]+[nums[n-1]]) return ret #方法二:dfs class Solution: """ @param nums: A set of numbers. @return: A list of lists. All valid subsets. """ def subsetsWithDup(self, nums): # write your code here size=len(nums) if size==0: return [[]] nums.sort() ret=[] self.dfs(nums,0,size,ret) return ret def dfs(self,nums,begin,size,ret,temp=[]): if temp not in ret: ret.append(temp[:]) if begin==size: return for i in range(begin,size): temp.append(nums[i]) self.dfs(nums,i+1,size,ret,temp) temp.pop()
582. Word Break II
Description
给一字串s和单词的字典dict,在字串中增加空格来构建一个句子,并且所有单词都来自字典。
返回所有有可能的句子。
Example
样例 1:
输入:"lintcode",["de","ding","co","code","lint"]
输出:["lint code", "lint co de"]
解释:
插入一个空格是"lint code",插入两个空格是 "lint co de"
样例 2:
输入:"a",[]
输出:[]
解释:字典为空
#coding:utf-8 """ 582. Word Break II Description Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word. Return all such possible sentences. Example 1: Input:"lintcode",["de","ding","co","code","lint"] Output:["lint code", "lint co de"] Explanation: insert a space is "lint code",insert two spaces is "lint co de". Example 2: Input:"a",[] Output:[] Explanation:dict is null. """ #带记忆化的DFS,普通DFS会超时 #参考:https://leetcode-cn.com/problems/word-break-ii/solution/dan-ci-chai-fen-ii-by-leetcode/ class Solution: """ @param: s: A string @param: wordDict: A set of words. @return: All possible sentences. """ def wordBreak(self, s, wordDict): # write your code here if len(wordDict)==0 or len(s)==0: return [] self.memory={} ret = self.dfs(s,0,len(s)+1,wordDict) return ret def dfs(self,s,begin,end,wordDict): ret=[] for i in range(begin+1,end): sub = s[begin:i] if sub in wordDict: if i==end-1: ret.append(sub) return ret if i not in self.memory: temp= self.dfs(s,i,end,wordDict) self.memory[i]=temp else: temp = self.memory[i] if temp: for item in temp: ret.append(sub+" "+item) if i==end-1: return ret if __name__=="__main__": s = Solution() print(s.wordBreak("lintcode",["de","ding","co","code","lint"])) print(s.wordBreak("a",[])) print(s.wordBreak("aaaaaaaa",["aaaa","aa","aaa"])) print(s.wordBreak("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", ["a","aa","aaa","aaaa","aaaaa","aaaaaa","aaaaaaa","aaaaaaaa","aaaaaaaaa","aaaaaaaaaa"]))
192. Wildcard Matching
Description
判断两个可能包含通配符“?”和“*”的字符串是否匹配。匹配规则如下:
- '?' 可以匹配任何单个字符。
- '*' 可以匹配任意字符串(包括空字符串)。
两个串完全匹配才算匹配成功。
Example
样例1
输入:
"aa"
"a"
输出: false
输出2
输入:
"aa"
"aa"
输出: true
输出3
输入:
"aaa"
"aa"
输出: false
输出4
输入:
"aa"
"*"
输出: true
说明: '*' 可以替换任何字符串
输出5
输入:
"aa"
"a*"
输出: true
样例6
输入:
"ab"
"?*"
输出: true
说明: '?' -> 'a' '*' -> 'b'
样例7
输入:
"aab"
"c*a*b"
输出: false
#coding:utf-8 """ 192. Wildcard Matching Description Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single character. '*' Matches any sequence of characters (including the empty sequence). The matching should cover the entire input string (not partial). Example 1 Input: "aa" "a" Output: false Example 2 Input: "aa" "aa" Output: true Example 3 Input: "aaa" "aa" Output: false Example 4 Input: "aa" "*" Output: true Explanation: '*' can replace any string Example 5 Input: "aa" "a*" Output: true Example 6 Input: "ab" "?*" Output: true Explanation: '?' -> 'a' '*' -> 'b' Example 7 Input: "aab" "c*a*b" Output: false """ #动态规划 https://blog.csdn.net/qq_27139155/article/details/80094880 class Solution: """ @param s: A string @param p: A string includes "?" and "*" @return: is Match? """ def isMatch(self, s, p): # write your code here if len(s)!=0 and len(p)==0: return False #注意dp的初始化,dp[i][0]全为0,dp[0][0]=1,对于dp[0][j]需要简单判断 dp = [[0 for i in range(len(p)+1)] for j in range(len(s)+1)] dp[0][0]=1 for i in range(1,len(p)+1): if p[i-1]=="*": dp[0][i]=dp[0][i-1] else: dp[0][i]=0 for i in range(1,len(s)+1): for j in range(1,len(p)+1): if p[j-1]=="*": dp[i][j]=dp[i-1][j] or dp[i][j-1] or dp[i-1][j-1] elif p[j-1]=="?" or p[j-1]==s[i-1]: dp[i][j]=dp[i-1][j-1] else: dp[i][j]=0 return dp[len(s)][len(p)]==1 #True of False if __name__=="__main__": s = Solution() print(s.isMatch("","*")) print(s.isMatch("aa","a")) print(s.isMatch("aab","c*a*b")) print(s.isMatch("aa","a*")) print(s.isMatch("aaa","aa"))
154. Regular Expression Matching
Description
实现支持'.'和'*'的正则表达式匹配。
'.'匹配任意一个字母。
'*'匹配零个或者多个前面的元素。
匹配应该覆盖整个输入字符串,而不仅仅是一部分。
需要实现的函数是:bool isMatch(string s, string p)
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true
Example
样例 1:
输入:"aa","a"
输出:false
解释:
无法匹配
样例 2:
输入:"aa","a*"
输出:true
解释:
'*' 可以重复 a
#coding:utf-8 """ 154. Regular Expression Matching Description Implement regular expression matching with support for '.' and '*'. '.' Matches any single character. '*' Matches zero or more of the preceding element. The matching should cover the entire input string (not partial). The function prototype should be: bool isMatch(string s, string p) isMatch("aa","a") → false isMatch("aa","aa") → true isMatch("aaa","aa") → false isMatch("aa", "a*") → true isMatch("aa", ".*") → true isMatch("ab", ".*") → true isMatch("aab", "c*a*b") → true #*也可以自己为空,也可以消掉前面一个字母, Example Example 1: Input:"aa","a" Output:false Explanation: unable to match Example 2: Input:"aa","a*" Output:true Explanation: '*' can repeat a """ #动态规划:https://www.jianshu.com/p/32925a05c699 class Solution: """ @param s: A string @param p: A string includes "." and "*" @return: A boolean """ def isMatch(self, s, p): # write your code here slen= len(s) plen = len(p) if slen!=0 and plen==0: return False dp=[[0 for i in range(plen+1)] for j in range(slen+1)] dp[0][0]=1 for i in range(1,plen+1): if p[i-1]=="*": if i==1: dp[0][i]=1 else: dp[0][i]=dp[0][i-2] #*能将i位消除掉 else: dp[0][i]=0 for i in range(1,slen+1): for j in range(1,plen+1): if p[j-1]=="." or p[j-1]==s[i-1]: dp[i][j]=dp[i-1][j-1] elif p[j-1]=="*": if j-2>=0: if (s[i-1]==p[j-2] or p[j-2]=="."): dp[i][j]=dp[i-1][j-1] or dp[i][j-1] or dp[i-1][j] or dp[i][j-2] else: dp[i][j]=dp[i][j-2] if j==1: dp[i][j]=(s[i-1]=="") else: dp[i][j]=0 return dp[slen][plen]==1 if __name__=="__main__": s = Solution() print(s.isMatch("aa","a")) print(s.isMatch("aa","aa")) print(s.isMatch("aaa","aa")) print(s.isMatch("aa", "a*")) print(s.isMatch("aa", ".*")) print(s.isMatch("ab", ".*")) print(s.isMatch("aab", "c*a*b")) print(s.isMatch("aasdfasdfasdfasdfas","aasdf.*asdf.*asdf.*asdf.*s")) print(s.isMatch("lintcode","*"))
425. Letter Combinations of a Phone Number
Description
给一个不包含'0'
和'1'
的数字字符串,每个数字代表一个字母,请返回其所有可能的字母组合。
下图的手机按键图,就表示了每个数字可以代表的字母。
1 | 2 ABC | 3 DEF |
---|---|---|
4 GHI |
5 JKL |
6 MNO |
7 PQRS |
8 TUV |
9 WXYZ |
以上的答案是按照词典编撰顺序进行输出的,不过,在做本题时,你也可以任意选择你喜欢的输出顺序。
Example
样例 1:
输入: "23"
输出: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]
解释:
'2' 可以是 'a', 'b' 或 'c'
'3' 可以是 'd', 'e' 或 'f'
样例 2:
输入: "5"
输出: ["j", "k", "l"]
#coding:utf-8 """ 425. Letter Combinations of a Phone Number Description Given a digit string excluded '0' and '1', return all possible letter combinations that the number could represent. A mapping of digit to letters (just like on the telephone buttons) is given below. 1 2ABC 3DEF 4GHI 5JKL 6MNO 7PQRS 8TUV 9WXYZ Although the answer above is in lexicographical order, your answer could be in any order you want. Example 1: Input: "23" Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"] Explanation: '2' could be 'a', 'b' or 'c' '3' could be 'd', 'e' or 'f' Example 2: Input: "5" Output: ["j", "k", "l"] """ class Solution: """ @param digits: A digital string @return: all posible letter combinations """ def letterCombinations(self, digits): # write your code here length = len(digits) if length==0: return [] ret=[] self.di_letters=["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"] self.dfs(digits,0,ret) return ret def dfs(self,digits,index,ret,temp=[]): if index==len(digits): ret.append("".join(temp)) return letters = self.di_letters[int(digits[index])] for i in letters: temp.append(i) self.dfs(digits,index+1,ret,temp) temp.pop() if __name__=="__main__": s = Solution() print(s.letterCombinations("23")) print(s.letterCombinations("5"))
34. N-Queens II
Description
根据n皇后问题,现在返回n皇后不同的解决方案的数量而不是具体的放置布局。 (即任意两个皇后都不能处于同一行、同一列或同一斜线上)
Example
例1:
输入: n=1
输出: 1
解释:
1:
1
例2:
输入: n=4
输出: 2
解释:
1:
0 0 1 0
1 0 0 0
0 0 0 1
0 1 0 0
2:
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
#coding:utf-8 """ Description 34. N-Queens II Follow up for N-Queens problem. (即任意两个皇后都不能处于同一行、同一列或同一斜线上) Now, instead outputting board configurations, return the total number of distinct solutions. Example 1: Input: n=1 Output: 1 Explanation: 1: 1 Example 2: Input: n=4 Output: 2 Explanation: 1: 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 2: 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 """ class Solution: """ @param n: The number of queens. @return: The total number of distinct solutions. """ def totalNQueens(self, n): # write your code here if n==0: return 0 self.num=0 self.dfs(n,0) return self.num def dfs(self, n, index, ret=[]): if index==n: self.num+=1 return temp=[] for i in range(index): temp.append(ret[i]+(index-i)) temp.append(ret[i]-(index-i)) for i in range(n): if i not in (temp+ret): ret.append(i) self.dfs(n,index+1,ret) ret.pop()
33. N-Queens
Description
n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击。
给定一个整数n,返回所有不同的n皇后问题的解决方案。
每个解决方案包含一个明确的n皇后放置布局,其中“Q”和“.”分别表示一个女王和一个空位置。
Example
例1:
输入:1
输出:
[["Q"]]
例2:
输入:4
输出:
[
// Solution 1
[".Q..",
"...Q",
"Q...",
"..Q."
],
// Solution 2
["..Q.",
"Q...",
"...Q",
".Q.."
]
]
Challenge
你能否不使用递归完成?
#coding:utf-8 """ 33. N-Queens Description The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. Given an integer n, return all distinct solutions to the n-queens puzzle. Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively. Example 1: Input:1 Output: [["Q"]] Example 2: Input:4 Output: [ // Solution 1 [".Q..", "...Q", "Q...", "..Q." ], // Solution 2 ["..Q.", "Q...", "...Q", ".Q.." ] ] """ class Solution: """ @param: n: The number of queens @return: All distinct solutions """ def solveNQueens(self, n): # write your code here if n==0: return 0 ret=[] self.dfs(n, 0, ret) return ret def dfs(self, n, index, ret, temp=[]): if index==n: m = self.tomap(n, temp) ret.append(m) s=[] for i in range(index): s.append(temp[i]+(index-i)) s.append(temp[i]-(index-i)) for i in range(n): if i not in (s+temp): temp.append(i) self.dfs(n,index+1,ret,temp) temp.pop() def tomap(self, n, temp): m=[] for i in temp: line = "."*i+"Q"+"."*(n-i-1) m.append(line) return m
16. Permutations II
Description
给出一个具有重复数字的列表,找出列表所有不同的排列。
Example
样例 1:
输入:[1,1]
输出:
[
[1,1]
]
样例 2:
输入:[1,2,2]
输出:
[
[1,2,2],
[2,1,2],
[2,2,1]
]
Challenge
使用递归和非递归分别完成该题。
#coding:utf-8 """ 16. Permutations II Description Given a list of numbers with duplicate number in it. Find all unique permutations. Example 1: Input: [1,1] Output: [ [1,1] ] Example 2: Input: [1,2,2] Output: [ [1,2,2], [2,1,2], [2,2,1] ] Challenge Using recursion to do it is acceptable. If you can do it without recursion, that would be great! """ class Solution: """ @param: : A list of integers @return: A list of unique permutations """ def permuteUnique(self, nums): # write your code here length=len(nums) if length==0: return [[]] ret=[] used=[False]*length #作为掩码,不重复用 self.dfs(nums, ret, used) return ret def dfs(self, nums, ret, used, temp=[]): if len(temp)==len(nums): if temp not in ret: ret.append(temp.copy()) return for i in range(len(nums)): if not used[i]: temp.append(nums[i]) used[i]=True self.dfs(nums, ret, used,temp) used[i]=False temp.pop()
15. Permutations (和16完全一样?)
Description
给定一个数字列表,返回其所有可能的排列。
你可以假设没有重复数字。
Example
样例 1:
输入:[1]
输出:
[
[1]
]
样例 2:
输入:[1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
Challenge
使用递归和非递归分别解决。
#coding:utf-8 """ 15. Permutations Description Given a list of numbers, return all possible permutations. You can assume that there is no duplicate numbers in the list. Example 1: Input: [1] Output: [ [1] ] Example 2: Input: [1,2,3] Output: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] Challenge Do it without recursion. """ class Solution: """ @param: nums: A list of integers. @return: A list of permutations. """ def permute(self, nums): # write your code here length=len(nums) if length==0: return [[]] ret=[] used=[False]*length #作为掩码,不重复用 self.dfs(nums, ret, used) return ret def dfs(self, nums, ret, used, temp=[]): if len(temp)==len(nums): if temp not in ret: ret.append(temp.copy()) return for i in range(len(nums)): if not used[i]: temp.append(nums[i]) used[i]=True self.dfs(nums, ret, used,temp) used[i]=False temp.pop()
Lintcode 829. Word Pattern II
Description
给定一个pattern
和一个字符串str
,查找str
是否遵循相同的模式。
这里遵循的意思是一个完整的匹配,在一个字母的模式
和一个非空的单词str
之间有一个双向连接的模式对应。(如果a
对应s
,那么b
不对应s
。例如,给定的模式= "ab"
, str = "ss"
,返回false
)。
您可以假设模式
和str
只包含小写字母
Example
样例1
输入:
pattern = "abab"
str = "redblueredblue"
输出: true
说明: "a"->"red","b"->"blue"
样例2
输入:
pattern = "aaaa"
str = "asdasdasdasd"
输出: true
说明: "a"->"asd"
样例3
输入:
pattern = "aabb"
str = "xyzabcxzyabc"
输出: false
#coding:utf-8 """ 829. Word Pattern II Description Given a pattern and a string str, find if str follows the same pattern. Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty substring in str.(i.e if a corresponds to s, then b cannot correspond to s. For example, given pattern = "ab", str = "ss", return false.) You may assume both pattern and str contains only lowercase letters. Example 1 Input: pattern = "abab" str = "redblueredblue" Output: true Explanation: "a"->"red","b"->"blue" Example 2 Input: pattern = "aaaa" str = "asdasdasdasd" Output: true Explanation: "a"->"asd" Example 3 Input: pattern = "aabb" str = "xyzabcxzyabc" Output: false """ class Solution: """ @param pattern: a string,denote pattern string @param str: a string, denote matching string @return: a boolean """ def wordPatternMatch(self, pattern, str): # write your code here if len(pattern)>len(str): return False self.ret=False pattern_set = set(pattern) map_dict = {i:"" for i in pattern} self.dfs(pattern,str,0,0,pattern_set,map_dict) return self.ret def dfs(self,pattern,str,index,substr_length,pattern_set,map_dict): if index==len(pattern): if substr_length==len(str): self.ret=True return pat = pattern[index] if map_dict[pat]!="": temp=map_dict[pat] if temp!=str[substr_length:substr_length+len(temp)]: return else: self.dfs(pattern,str,index+1,substr_length+len(temp),pattern_set,map_dict) return #必须得返回 for i in range(substr_length+1,len(str)+1): sub_str = str[substr_length:i] if sub_str not in map_dict.values(): map_dict[pat]=sub_str else: if map_dict[pat]!=sub_str: #pattern中一个字符对应一个唯一substr continue self.dfs(pattern,str,index+1,substr_length+len(sub_str),pattern_set,map_dict) if self.ret==True: return map_dict[pat]="" if __name__=="__main__": s = Solution() print(s.wordPatternMatch(pattern = "aabb",str = "xyzabcxzyabc")) print(s.wordPatternMatch(pattern = "aaaa",str = "asdasdasdasd")) print(s.wordPatternMatch(pattern = "abab",str = "redblueredblue")) print(s.wordPatternMatch(pattern = "d",str = "ef")) print(s.wordPatternMatch(pattern = "lwpstyfsjf",str = "htkvcxwxkymrvrpcxw"))
lintcode 132. Word Search II
Description
给出一个由小写字母组成的矩阵和一个字典。找出所有同时在字典和矩阵中出现的单词。一个单词可以从矩阵中的任意位置开始,可以向左/右/上/下四个相邻方向移动。一个字母在一个单词中只能被使用一次。且字典中不存在重复单词
Example
样例 1:
输入:["doaf","agai","dcan"],["dog","dad","dgdg","can","again"]
输出:["again","can","dad","dog"]
解释:
d o a f
a g a i
d c a n
矩阵中查找,返回 ["again","can","dad","dog"]。
样例 2:
输入:["a"],["b"]
输出:[]
解释:
a
矩阵中查找,返回 []。
Challenge
使用单词查找树来实现你的算法
#coding:utf-8 """ lintcode 132. Word Search II Description Given a matrix of lower alphabets and a dictionary. Find all words in the dictionary that can be found in the matrix. A word can start from any position in the matrix and go left/right/up/down to the adjacent position. One character only be used once in one word. No same word in dictionary Example 1: Input:["doaf","agai","dcan"],["dog","dad","dgdg","can","again"] Output:["again","can","dad","dog"] Explanation: d o a f a g a i d c a n search in Matrix,so return ["again","can","dad","dog"]. Example 2: Input:["a"],["b"] Output:[] Explanation: a search in Matrix,return []. Challenge Using trie to implement your algorithm. """ #参考:https://www.jiuzhang.com/solutions/word-search-ii/#tag-highlight-lang-python #构建trie tree class TrieNode(object): def __init__(self): self.children={} self.is_word=False self.word=None class TrieTree(object): def __init__(self): self.root = TrieNode() def add(self,word): node =self.root for c in word: if c not in node.children: node.children[c]=TrieNode() node = node.children[c] node.is_word=True node.word=word def search(self,word): node = self.root for c in word: if c not in node.children: return None node = node.children[c] return node DIRECTIONS=[(0,1),(0,-1),(-1,0),(1,0)] class Solution: """ @param board: A list of lists of character @param words: A list of string @return: A list of string """ def wordSearchII(self, board, words): # write your code here if len(words)==0 or len(board)==0: return [] trie = TrieTree() for word in words: trie.add(word) ret = [] root = trie.root for i in range(len(board)): for j in range(len(board[i])): self.search(board,i,j,root,ret,set([(i,j)])) return ret def search(self,board,i,j,node,ret,visited): node = node.children.get(board[i][j],None) if node==None: return if node.is_word and node.word not in ret: ret.append(node.word) for d in DIRECTIONS: x,y = i+d[0],j+d[1] if self.in_board(x,y,board): if (x,y) not in visited: visited.add((x,y)) self.search(board,x,y,node,ret,visited) visited.remove((x,y)) def in_board(self,x,y,board): if 0<= x <len(board) and 0<=y<len(board[x]): return True #用图的方法,如何避免一个字母不被重复利用? # class Solution: # """ # @param board: A list of lists of character # @param words: A list of string # @return: A list of string # """ # def wordSearchII(self, board, words): # #write your code here # if len(words)==0 or len(board)==0: # return [] # #建立图 # graph = dict() # length1=len(board) # for i in range(length1): # length2 = len(board[i]) # for j in range(length2): # if board[i][j] not in graph: # graph[board[i][j]]=set() # if i>0 and j<len(board[i-1]): # graph[board[i][j]].add(board[i-1][j]) # if i<length1-1 and j<len(board[i+1]): # graph[board[i][j]].add(board[i+1][j]) # if j>0: # graph[board[i][j]].add(board[i][j-1]) # if j<length2-1: # graph[board[i][j]].add(board[i][j+1]) # ret=[] # for word in words: # if word[0] in graph: # self.dfs(graph,word,1,ret) # return ret # def dfs(self,graph,word,index,ret): # if index==len(word): # ret.append(word) # return # char = word[index] # if char not in graph[word[index-1]]: # return # self.dfs(graph,word,index+1,ret) if __name__=="__main__": s = Solution() print(s.wordSearchII(["doaf","agai","dcan"],["dog","dad","dgdg","can","again"])) print(s.wordSearchII(["doaf","agai","can"],["dog","dad","dgdg","can","again"])) print(s.wordSearchII(["a"],["b"])) print(s.wordSearchII(["abce","sfcs","adee"],["see","se"])) print(s.wordSearchII(["b","a","b","b","a"],["babbab","b","a","ba"])) print(s.wordSearchII(["abce","sfcs","adee"],["abcb","ninechapter","lintcode"])) print(s.wordSearchII(["abce","sfcs","adee"],["as","ab","cf","da","ee","e","adee","eeda"]))
Lintcode 121. Word Ladder II
Description
给出两个单词(start和end)和一个字典,找出所有从start到end的最短转换序列。
变换规则如下:
- 每次只能改变一个字母。
- 变换过程中的中间单词必须在字典中出现。
- 所有单词具有相同的长度。
- 所有单词都只包含小写字母。
- 题目确保存在合法的路径。
Example
样例 1:
输入:start = "a",end = "c",dict =["a","b","c"]
输出:[["a","c"]]
解释:
"a"->"c"
样例 2:
输入:start ="hit",end = "cog",dict =["hot","dot","dog","lot","log"]
输出:[["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]]
解释:
1."hit"->"hot"->"dot"->"dog"->"cog"
2."hit"->"hot"->"lot"->"log"->"cog"
第一个序列的字典序小于第二个。
#coding:utf-8 """ Lintcode 121. Word Ladder II Description Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, output sequence in dictionary order. Transformation rule such that: Only one letter can be changed at a time Each intermediate word must exist in the dictionary All words have the same length. All words contain only lowercase alphabetic characters. At least one solution exists. Example 1: Input:start = "a",end = "c",dict =["a","b","c"] Output:[["a","c"]] Explanation: "a"->"c" Example 2: Input:start ="hit",end = "cog",dict =["hot","dot","dog","lot","log"] Output:[["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]] Explanation: 1."hit"->"hot"->"dot"->"dog"->"cog" 2."hit"->"hot"->"lot"->"log"->"cog" The dictionary order of the first sequence is less than that of the second. """ #参考:https://www.jiuzhang.com/solutions/word-ladder-ii/#tag-highlight-lang-python class Solution: """ @param: start: a string @param: end: a string @param: dict: a set of string @return: a list of lists of string """ def findLadders(self, start, end, dict): # write your code here if (not start) or (not end) or len(dict)==0: return [] from collections import defaultdict if start not in dict: dict.append(start) if end not in dict: dict.append(end) #构建图 graph=defaultdict(list) #用list,不用set,保证word的字典顺序 for word in dict: for i in range(len(word)): label = word[:i]+"_"+word[i+1:] if word not in graph[label]: graph[label].append(word) ret=[] distance = self.bfs(end,graph) self.dfs(graph,start,end,distance,ret,[start]) return ret def bfs(self,end,graph): distance={end:0} q = [end] seen={end} while q: cur = q.pop(0) for i in range(len(cur)): for next in graph[cur[:i]+"_"+cur[i+1:]]: if next not in distance: distance[next] = distance[cur]+1 if next not in seen: seen.add(next) q.append(next) return distance def dfs(self,graph,cur,end,distance,ret,path): if cur==end: ret.append(path.copy()) return for i in range(len(cur)): for next in graph[cur[:i]+"_"+cur[i+1:]]: if distance[next] != distance[cur]-1: continue path.append(next) self.dfs(graph,next,end,distance,ret,path) path.pop() #超时了!!!! # class Solution: # """ # @param: start: a string # @param: end: a string # @param: dict: a set of string # @return: a list of lists of string # """ # def findLadders(self, start, end, dict): # # write your code here # if (not start) or (not end) or len(dict)==0: # return [] # from collections import defaultdict # if start not in dict: # dict.append(start) # if end not in dict: # dict.append(end) # #构建图 # graph=defaultdict(list) #用list,不用set,保证word的字典顺序 # for word in dict: # for i in range(len(word)): # label = word[:i]+"_"+word[i+1:] # if word not in graph[label]: # graph[label].append(word) # self.min_path = self.max_depth = len(dict) # ret = [] # self.dfs(graph,0,start,end,ret,set([start])) # ret=[path for path in ret if len(path)<=self.min_path] # return ret # def dfs(self,graph,depth,cur,end,ret,visited,temp=[]): # if cur==end: # temp.append(cur) # if temp not in ret and len(temp)<=self.min_path: # ret.append(temp.copy()) # self.min_path = len(temp) # temp.pop() # return # if depth==self.max_depth: # return # for i in range(len(cur)): # temp.append(cur) # for next in graph[cur[:i]+"_"+cur[i+1:]]: # if next not in visited: # visited.add(next) # self.dfs(graph,depth+1,next,end,ret,visited,temp) # visited.remove(next) # temp.pop() if __name__=="__main__": s =Solution() print(s.findLadders("a","c",["a","b","c"])) print(s.findLadders(start ="hit",end = "cog",dict =["hot","dot","dog","lot","log"])) print(s.findLadders(start ="qa",end = "sq",dict =["si","go","se","cm","so","ph","mt","db","mb","sb","kr","ln","tm","le","av","sm","ar","ci","ca","br","ti","ba","to","ra","fa","yo","ow","sn","ya","cr","po","fe","ho","ma","re","or","rn","au","ur","rh","sr","tc","lt","lo","as","fr","nb","yb","if","pb","ge","th","pm","rb","sh","co","ga","li","ha","hz","no","bi","di","hi","qa","pi","os","uh","wm","an","me","mo","na","la","st","er","sc","ne","mn","mi","am","ex","pt","io","be","fm","ta","tb","ni","mr","pa","he","lr","sq","ye"]))
(七)数据结构(Data Structure)
Lintcode 642. Moving Average from Data Stream
Description
给出一串整数流和窗口大小,计算滑动窗口中所有整数的平均值。
Example
样例1 :
MovingAverage m = new MovingAverage(3);
m.next(1) = 1 // 返回 1.00000
m.next(10) = (1 + 10) / 2 // 返回 5.50000
m.next(3) = (1 + 10 + 3) / 3 // 返回 4.66667
m.next(5) = (10 + 3 + 5) / 3 // 返回 6.00000
#coding:utf-8 """ Lintcode 642. Moving Average from Data Stream Description Given a stream of integers and a window size, calculate the moving average of all integers in the sliding window. Example 1: MovingAverage m = new MovingAverage(3); m.next(1) = 1 // return 1.00000 m.next(10) = (1 + 10) / 2 // return 5.50000 m.next(3) = (1 + 10 + 3) / 3 // return 4.66667 m.next(5) = (10 + 3 + 5) / 3 // return 6.00000 """ class MovingAverage: """ @param: size: An integer """ def __init__(self, size): # do intialization if necessary self.size = size self.numbers = [] self._sum = 0 self.start=0 """ @param: val: An integer @return: """ def next(self, val): # write your code here self.numbers.append(val) self._sum+=val length = len(self.numbers) if length>self.size: self._sum-=self.numbers[self.start] self.start+=1 return self._sum/(length-self.start) # Your MovingAverage object will be instantiated and called as such: # obj = MovingAverage(size) # param = obj.next(val)
Lintcode 209. First Unique Character in a String
Description
给出一个字符串,找出第一个只出现一次的字符。
Example
样例 1:
输入: "abaccdeff"
输出: 'b'
解释:
'b' 是第一个出现一次的字符
样例 2:
输入: "aabccd"
输出: 'b'
解释:
'b' 是第一个出现一次的字符
#coding:utf-8 """ Lintcode 209. First Unique Character in a String Description Find the first unique character in a given string. You can assume that there is at least one unique character in the string. Example 1: Input: "abaccdeff" Output: 'b' Explanation: There is only one 'b' and it is the first one. Example 2: Input: "aabccd" Output: 'b' Explanation: 'b' is the first one. """ class Solution: """ @param str: str: the given string @return: char: the first unique character in a given string """ def firstUniqChar(self, str): # Write your code here length=len(str) if length==0: return "" c = dict() for i in str: if i not in c: c[i]=0 else: c[i]+=1 for i in str: if c[i]==0: return i
Lintcode 657. Insert Delete GetRandom O(1)
Description
设计一个数据结构实现在平均 O(1)
的复杂度下执行以下所有的操作。
-
insert(val)
: 如果这个元素不在set中,则插入。 -
remove(val)
: 如果这个元素在set中,则从set中移除。 -
getRandom
: 随机从set中返回一个元素。每一个元素返回的可能性必须相同。
Example
// 初始化空集set
RandomizedSet randomSet = new RandomizedSet();
// 1插入set中。返回正确因为1被成功插入
randomSet.insert(1);
// 返回错误因为2不在set中
randomSet.remove(2);
// 2插入set中,返回正确,set现在有[1,2]。
randomSet.insert(2);
// getRandom 应该随机的返回1或2。
randomSet.getRandom();
// 从set中移除1,返回正确。set现在有[2]。
randomSet.remove(1);
// 2已经在set中,返回错误。
randomSet.insert(2);
// 因为2是set中唯一的数字,所以getRandom总是返回2。
randomSet.getRandom();
#coding:utf-8 """ Lintcode 657. Insert Delete GetRandom O(1) Description Design a data structure that supports all following operations in average O(1) time. insert(val): Inserts an item val to the set if not already present. remove(val): Removes an item val from the set if present. getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned. Example // Init an empty set. RandomizedSet randomSet = new RandomizedSet(); // Inserts 1 to the set. Returns true as 1 was inserted successfully. randomSet.insert(1); // Returns false as 2 does not exist in the set. randomSet.remove(2); // Inserts 2 to the set, returns true. Set now contains [1,2]. randomSet.insert(2); // getRandom should return either 1 or 2 randomly. randomSet.getRandom(); // Removes 1 from the set, returns true. Set now contains [2]. randomSet.remove(1); // 2 was already in the set, so return false. randomSet.insert(2); // Since 2 is the only number in the set, getRandom always return 2. randomSet.getRandom(); """ #hashmap + list (注意remove时,将末尾元素和移出元素互换,再移除) class RandomizedSet: def __init__(self): # do intialization if necessary self.store = dict() self.vals = [] """ @param: val: a value to the set @return: true if the set did not already contain the specified element or false """ def insert(self, val): # write your code here if val not in self.store: self.vals.append(val) self.store[val]=len(self.vals)-1 return True return False """ @param: val: a value from the set @return: true if the set contained the specified element or false """ def remove(self, val): # write your code here if val in self.store: index = self.store[val] self.vals[index]=self.vals[-1] self.store[self.vals[-1]]=index self.vals.pop() del self.store[val] return True return False """ @return: Get a random element from the set """ def getRandom(self): # write your code here import random return random.choice(self.vals) # Your RandomizedSet object will be instantiated and called as such: # obj = RandomizedSet() # param = obj.insert(val) # param = obj.remove(val) # param = obj.getRandom()