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刷题笔记(一)

posted @ 2021-05-16 13:08  silence_cho  阅读(223)  评论(0编辑  收藏  举报