• lintcode刷题笔记(二)


      接着上篇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"))
            
    680

     

    136.Palindrome Partitioning

    Description

    给定字符串 s, 需要将它分割成一些子串, 使得每个子串都是回文串.

    返回所有可能的分割方案.

    1. 不同的方案之间的顺序可以是任意的.
    2. 一种分割方案中的每个子串都必须是 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"))
    136

     153. Combination Sum II

    Description

    给定一个数组 num 和一个整数 target. 找到 num 中所有的数字之和为 target 的组合.

    1. 在同一个组合中, num 中的每一个数字仅能被使用一次.
    2. 所有数值 (包括 target ) 都是正整数.
    3. 返回的每一个组合内的数字必须是非降序的.
    4. 返回的所有组合之间可以是任意顺序.
    5. 解集不能包含重复的组合.

    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))
        
    153

    152. Combinations

    Description

    给定两个整数 nk. 返回从 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))
                
    152
     
    135. Combination Sum

    Description

    给定一个候选数字的集合 candidates 和一个目标值 target. 找到 candidates 中所有的和为 target 的组合.

    在同一个组合中, candidates 中的某个数字不限次数地出现.

    1. 所有数值 (包括 target ) 都是正整数.
    2. 返回的每一个组合内的数字必须是非降序的.
    3. 返回的所有组合之间可以是任意顺序.
    4. 解集不能包含重复的组合.
       

    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()
    135

    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()
    18

    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()
    17

     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"]))
        
    583

     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"))
            
                    
            
    192

     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","*"))
        
        
    154

     425. Letter Combinations of a Phone Number

    Description

    给一个不包含'0''1'的数字字符串,每个数字代表一个字母,请返回其所有可能的字母组合。

    下图的手机按键图,就表示了每个数字可以代表的字母。

    12
    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"))
            
    425

     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()
                
            
    34

    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 
    33

    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()
    16

    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()
    15

    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"))
        
            
            
            
          
          
    829

     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"]))
                    
                        
                
            
            
            
    132

    Lintcode 121. Word Ladder II

    Description

    给出两个单词(startend)和一个字典,找出所有从startend的最短转换序列。

    变换规则如下:

    1. 每次只能改变一个字母。
    2. 变换过程中的中间单词必须在字典中出现。
      1.   所有单词具有相同的长度。
      2.   所有单词都只包含小写字母。
      3.   题目确保存在合法的路径。

    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"]))
        
    
    
        
            
    121

     (七)数据结构(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)
    642

    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
        
    209

    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()
    657

    lintcode刷题笔记(一)

  • 相关阅读:
    作业四:结对编程项目---四则运算
    作业三: 代码规范、代码复审、PSP
    自动生成四则运算题目
    源程序版本管理软件和项目管理软件的优缺点
    学习进度表
    第一周随笔
    对之前问题的回答
    结对编程——四则运算
    PSP
    代码复审
  • 原文地址:https://www.cnblogs.com/silence-cho/p/11256149.html
Copyright © 2020-2023  润新知