[LeetCode]-Python刷题第三周(栈和队列)

20. Valid Parentheses 合法括号(Easy)

Given a string containing just the characters '('')''{''}''[' and ']', determine if the input string is valid.

An input string is valid if:

  1. Open brackets must be closed by the same type of brackets.
  2. Open brackets must be closed in the correct order.

Note that an empty string is also considered valid.

Example 1:

Input: "()"
Output: true

Example 2:

Input: "()[]{}"
Output: true

Example 3:

Input: "(]"
Output: false

Example 4:

Input: "([)]"
Output: false

Example 5:

Input: "{[]}"
Output: true

栈Stack,经典的使用栈的题目。遍历字符串,如果为左括号,将其压入栈中,如果遇到为右括号,若此时栈为空,则直接返回false,如不为空,则取出栈顶元素,若为对应的左括号,是合法的继续循环,否则返回false。

class Solution(object):
    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        stack = []    #建立一个栈
        dict = {"]":"[", "}":"{", ")":"("}   #建立一个字典,成对应关系
        for char in s:     #循环
            if char in dict.values():   #如果在字符串中有左括号,就将这个字符添加在栈中
                stack.append(char)    
            elif char in dict.keys():   #如果字符中有右括号
                if stack == [] or dict[char] != stack.pop():      #如果栈是空的或者是这个字符对应的值不等于栈中取出的字符,就返回false
                    return False
            else:
                return True
        return stack == []   #如果最后栈为空就返回True
class Solution(object):
    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        stack, lookup = [], {"(": ")", "{": "}", "[": "]"}
        for parenthese in s:
            if parenthese in lookup:  # Cannot use if lookup[parenthese]: KeyError
                stack.append(parenthese)
            elif len(stack) == 0 or lookup[stack.pop()] != parenthese: # Cannot use not stack
                return False
        return len(stack) == 0
class Solution(object):
    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        stack = []
        m = {'(': ')', '[': ']', '{': '}'}
        n = [')', ']', '}']
        for i in s:
            if i in m:
                stack.append(i)
            elif i in n and stack:
                if m[stack.pop()] != i:
                    return False
            else:
                return False
        return len(stack) == 0

71. Simplify Path 简化路径(Medium)

Given an absolute path for a file (Unix-style), simplify it. Or in other words, convert it to the canonical path.

In a UNIX-style file system, a period . refers to the current directory. Furthermore, a double period .. moves the directory up a level. For more information, see: Absolute path vs relative path in Linux/Unix

Note that the returned canonical path must always begin with a slash /, and there must be only a single slash / between two directory names. The last directory name (if it exists) must not end with a trailing /. Also, the canonical path must be the shortest string representing the absolute path.

Example 1:

Input: "/home/"
Output: "/home"
Explanation: Note that there is no trailing slash after the last directory name.

Example 2:

Input: "/../"
Output: "/"
Explanation: Going one level up from the root directory is a no-op, as the root level is the highest level you can go.

Example 3:

Input: "/home//foo/"
Output: "/home/foo"
Explanation: In the canonical path, multiple consecutive slashes are replaced by a single one.

Example 4:

Input: "/a/./b/../../c/"
Output: "/c"

Example 5:

Input: "/a/../../b/../c//.//"
Output: "/c"

Example 6:

Input: "/a//bc/d//././/.."
Output: "/a/b/c"

1、".."表示跳到上一层目录,删掉它上面挨着的一个路径。

2、"."表示当前目录,直接去掉。

3、如果有多个"/"只保留一个。

4、如果最后有一个"/",去掉不要。

class Solution(object):
    def simplifyPath(self, path):
        """
        :type path: str
        :rtype: str
        """
        stack, tokens = [], path.split("/")   #建立一个栈, split() 通过指定分隔符对字符串进行切片,如果参数 num 有指定值,则分隔 num+1 个子字符串。参数(str:分隔符,num:分割次数,默认-1,即分割所有),返回分割后的字符串列表,不带有分隔符。本函数将字符串根据/分割成一段一段的。
        for token in tokens:   
            if token == ".." and stack:    #如果列表的值是..且栈不为空,
                stack.pop()    #就取出最上边的一个值
            elif token != ".." and token != "." and token:    #如果列表的字符不是..且字符不是.,且列表值为真,
                stack.append(token)   #就将这个值压入栈
        return "/" + "/".join(stack)  #join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。

388. Longest Absolute File Path 最长的绝对文件路径 (Medium)

Suppose we abstract our file system by a string in the following manner:

The string "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext" represents:

dir
    subdir1
    subdir2
        file.ext

The directory dir contains an empty sub-directory subdir1 and a sub-directory subdir2 containing a file file.ext.

The string "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"represents:

dir
    subdir1
        file1.ext
        subsubdir1
    subdir2
        subsubdir2
            file2.ext

The directory dir contains two sub-directories subdir1 and subdir2subdir1 contains a file file1.ext and an empty second-level sub-directory subsubdir1subdir2 contains a second-level sub-directory subsubdir2 containing a file file2.ext.

We are interested in finding the longest (number of characters) absolute path to a file within our file system. For example, in the second example above, the longest absolute path is "dir/subdir2/subsubdir2/file2.ext", and its length is 32 (not including the double quotes).

Given a string representing the file system in the above format, return the length of the longest absolute path to file in the abstracted file system. If there is no file in the system, return 0.

Note:

  • The name of a file contains at least a . and an extension.
  • The name of a directory or sub-directory will not contain a ..

 

Time complexity required: O(n) where n is the size of the input string.

Notice that a/aa/aaa/file1.txt is not the longest file path, if there is another path aaaaaaaaaaaaaaaaaaaaa/sth.png.

解法1:栈Stack

一个字符串表示文件系统的目录结构,里面包含\n(回车)和\t(tab)的特殊字符,要找到最长的绝对文件路径。
可用栈Stack, Array, Hash table来保存每一层的最长路径长度。以栈为例:

1. 将字符串以'\n'进行拆分,得到目录字符串数组,设置最大长度变量 maxLen = 0,设置一个 Stack,初始设为0层为0。

2. 对这个数组迭代,对于每个目录字符串统计其前面的'\t'个数, 个数加1就是当前目录的层深度,比如: 0个'\t',层数就是1,1个'\t',层数是2。

3. 比较当前目录层数和栈顶层数:

    1)如果目录层数大于栈顶层数:判断是否含'.' ,

       a. 不含'.',则是目录,计算当前目录长度(字符长度+1因为要多1个"/")+ 上层目录最大长度,长度入栈。

       b. 含'.' , 则为文件,计算当前文件长度(字符长度),此长度加上栈顶元素长度(上层目录最大长度)和maxLen比较取最大。

    2)如果目录层数小于栈顶层数:

       则弹出栈顶元素,用while循环,一直弹到栈顶的层小于当前层数。然后重复上面的a, b步骤

最后,返回maxLen.

解法2:哈希表HashMap

class Solution(object):
    def lengthLongestPath(self, input):
        """
        :type input: str
        :rtype: int
        """
        maxlen = 0
        pathlen = {0: 0}
        for line in input.splitlines():   #splitlines([keepends]) 按照行('\r', '\r\n', \n')分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符,默认为false。返回一个包含各行作为元素的列表。
            name = line.lstrip('\t')    #lstrip([chars]) 方法用于截掉字符串左边的空格或指定字符。chars --指定截取的字符。返回新的字符串
            depth = len(line) - len(name)
            if '.' in name:    #如果name中有.
                maxlen = max(maxlen, pathlen[depth] + len(name))
            else:
                pathlen[depth + 1] = pathlen[depth] + len(name) + 1
        return maxlen

394. Decode String 解码字符串 (Medium)

Given an encoded string, return it's decoded string.

The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times. Note that k is guaranteed to be a positive integer.

You may assume that the input string is always valid; No extra white spaces, square brackets are well-formed, etc.

Furthermore, you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, k. For example, there won't be input like 3a or 2[4].

Examples:

s = "3[a]2[bc]", return "aaabcbc".
s = "3[a2[c]]", return "accaccacc".
s = "2[abc]3[cd]ef", return "abcabccdcdcdef".
class Solution(object):
    def decodeString(self, s):
        """
        :type s: str
        :rtype: str
        """
        curnum = 0
        curstring = ''
        stack = []
        for char in s:
            if char == '[':    #如果字符是[
                stack.append(curstring)     #把当前字符压入栈
                stack.append(curnum)    #把当前数字压入栈
                curstring = ''    #重新赋值curstring  和curstring
                curnum = 0  
            elif char == ']':      #如果字符是]
                prenum = stack.pop()   #取出上边的字符和数字
                prestring = stack.pop()  
                curstring = prestring + prenum * curstring
            elif char.isdigit():    #isdigit() 方法检测字符串是否只由数字组成。只包含数字返回True,否则返回False。
                curnum = curnum * 10 + int(char)   #这里存在的目的是当[前面是一个好几位的数时的情况
            else:
                curstring += char
        return curstring

341. Flatten Nested List Iterator  展平嵌套列表迭代器  (Medium)

Given a nested list of integers, implement an iterator to flatten it.

Each element is either an integer, or a list -- whose elements may also be integers or other lists.

Example 1:

Input: [[1,1],2,[1,1]]
Output: [1,1,2,1,1]
Explanation: By calling next repeatedly until hasNext returns false, 
             the order of elements returned by next should be:
[1,1,2,1,1]
.

Example 2:

Input: [1,[4,[6]]]
Output: [1,4,6]
Explanation: By calling next repeatedly until hasNext returns false, 
             the order of elements returned by next should be:[1,4,6]。

将1个含有整数元素的嵌套链表压平,就是把所以元素按嵌套关系变成1个list。按题目要求要有next和hasNext两个函数。(这个题没搞明白)

# """
# This is the interface that allows for creating nested lists.
# You should not implement it, or speculate about its implementation
# """
#class NestedInteger(object):
#    def isInteger(self):
#        """
#        @return True if this NestedInteger holds a single integer, rather than a nested list.
#        :rtype bool
#        """
#
#    def getInteger(self):
#        """
#        @return the single integer that this NestedInteger holds, if it holds a single integer
#        Return None if this NestedInteger holds a nested list
#        :rtype int
#        """
#
#    def getList(self):
#        """
#        @return the nested list that this NestedInteger holds, if it holds a nested list
#        Return None if this NestedInteger holds a single integer
#        :rtype List[NestedInteger]
#        """

class NestedIterator(object):

    def __init__(self, nestedList):
        """
        Initialize your data structure here.
        :type nestedList: List[NestedInteger]
        """
        self.stack = []
        self.list = nestedList
        

    def next(self):
        """
        :rtype: int
        """
        return self.stack.pop()
        

    def hasNext(self):
        """
        :rtype: bool
        """
        while self.list or self.stack:    #当列表和栈都不为空时,
            if not self.stack:      #如果栈为空,就把链表中第一个数取出来放在栈里边
                self.stack.append(self.list.pop(0))              
            while self.stack and not self.stack[-1].isInteger():     #isInteger()判断是否为整数。-1:最后一个数。如果栈不为空,且最后一个数不是整数。
                top = self.stack.pop().getList()
                for e in top[::-1]:
                    self.stack.append(e)
            if self.stack and self.stack[-1].isInteger():
                return True
        return False
        

# Your NestedIterator object will be instantiated and called as such:
# i, v = NestedIterator(nestedList), []
# while i.hasNext(): v.append(i.next())

150. Evaluate Reverse Polish Notation 计算逆波兰表达式 (Medium)

Evaluate the value of an arithmetic expression in Reverse Polish Notation.

Valid operators are +-*/. Each operand may be an integer or another expression.

Note:

  • Division between two integers should truncate toward zero.
  • The given RPN expression is always valid. That means the expression would always evaluate to a result and there won't be any divide by zero operation.

Example 1:

Input: ["2", "1", "+", "3", "*"]
Output: 9
Explanation: ((2 + 1) * 3) = 9

Example 2:

Input: ["4", "13", "5", "/", "+"]
Output: 6
Explanation: (4 + (13 / 5)) = 6

Example 3:

Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
Output: 22
Explanation: 
  ((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

逆波兰表达式,所有操作符置于操作数的后面,因此也被称为后缀表示法。逆波兰记法不需要括号来标识操作符的优先级。

逆波兰记法中,操作符置于操作数的后面。例如表达“三加四”时,写作“3 4 +”,而不是“3 + 4”。如果有多个操作符,操作符置于第二个操作数的后面,所以常规中缀记法的“3 - 4 + 5”在逆波兰记法中写作“3 4 - 5 +”:先3减去4,再加上5。使用逆波兰记法的一个好处是不需要使用括号。例如中缀记法中“3 - 4 * 5”与“(3 - 4)*5”不相同,但后缀记法中前者写做“3 4 5 * -”,无歧义地表示“3 (4 5 *) -”;后者写做“3 4 - 5 *”。

逆波兰表达式的解释器一般是基于堆栈的。解释过程一般是:操作数入栈;遇到操作符时,操作数出栈,求值,将结果入栈;当一遍后,栈顶就是表达式的值。因此逆波兰表达式的求值使用堆栈结构很容易实现,并且能很快求值。

注意:逆波兰记法并不是简单的波兰表达式的反转。因为对于不满足交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法“/ 6 3”的逆波兰记法是“6 3 /”而不是“3 6 /”;数字的数位写法也是常规顺序。

解法1: 栈Stack

解法2: 递归

class Solution(object):
    def evalRPN(self, tokens):
        """
        :type tokens: List[str]
        :rtype: int
        """
        numerals, operators = [], {"+": operator.add, "-": operator.sub, "*": operator.mul, "/": operator.div}
        for token in tokens:
            if token not in operators:
                numerals.append(int(token))
            else:
                y, x = numerals.pop(), numerals.pop()
                numerals.append(int(operators[token](x * 1.0, y)))
        return numerals.pop()

385. Mini Parser  迷你解析器(Medium)

Given a nested list of integers represented as a string, implement a parser to deserialize it.

Each element is either an integer, or a list -- whose elements may also be integers or other lists.

Note: You may assume that the string is well-formed:

  • String is non-empty.
  • String does not contain white spaces.
  • String contains only digits 0-9[- ,].

 

Example 1:

Given s = "324",

You should return a NestedInteger object which contains a single integer 324.

 

Example 2:

Given s = "[123,[456,[789]]]",

Return a NestedInteger object containing a nested list with 2 elements:

1. An integer containing value 123.
2. A nested list containing two elements:
    i.  An integer containing value 456.
    ii. A nested list with one element:
         a. An integer containing value 789.

给了一个字符串表示的列表,返回一个NestedInteger形式的列表,其每个元素都是NestedInteger形式的整数对象。

# """
# This is the interface that allows for creating nested lists.
# You should not implement it, or speculate about its implementation
# """
#class NestedInteger(object):
#    def __init__(self, value=None):
#        """
#        If value is not specified, initializes an empty list.
#        Otherwise initializes a single integer equal to value.
#        """
#
#    def isInteger(self):
#        """
#        @return True if this NestedInteger holds a single integer, rather than a nested list.
#        :rtype bool
#        """
#
#    def add(self, elem):
#        """
#        Set this NestedInteger to hold a nested list and adds a nested integer elem to it.
#        :rtype void
#        """
#
#    def setInteger(self, value):
#        """
#        Set this NestedInteger to hold a single integer equal to value.
#        :rtype void
#        """
#
#    def getInteger(self):
#        """
#        @return the single integer that this NestedInteger holds, if it holds a single integer
#        Return None if this NestedInteger holds a nested list
#        :rtype int
#        """
#
#    def getList(self):
#        """
#        @return the nested list that this NestedInteger holds, if it holds a nested list
#        Return None if this NestedInteger holds a single integer
#        :rtype List[NestedInteger]
#        """

class Solution(object):
    def deserialize(self, s):
        """
        :type s: str
        :rtype: NestedInteger
        """
        def getNumber(nums):
            if isinstance(nums, int):
                return NestedInteger(nums)
            lst = NestedInteger()
            for num in nums:
                lst.add(getNumber(num))
            return lst
        return getNumber(eval(s))   #eval() 函数用来执行一个字符串表达式,并返回表达式的值。

155. Min Stack 最小栈 (Easy)

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.

  • push(x) -- Push element x onto stack.
  • pop() -- Removes the element on top of the stack.
  • top() -- Get the top element.
  • getMin() -- Retrieve the minimum element in the stack.

Example:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> Returns -3.
minStack.pop();
minStack.top();      --> Returns 0.
minStack.getMin();   --> Returns -2.

设计一个最小栈,实现push, pop, top, getMin四个功能。相比原来的栈多了一个功能,可以返回当前栈内的最小值。

解法1:使用2个栈,栈1记录进来的数,栈2记录目前的最小值。当有新数push进来的时候,如果栈2为空或者这个数小于栈2顶上的值,就把这个数推入栈2。当pop的数正好等于最小值时,说明当前栈内的最小值变化了,要弹出这个最小值,记录的下一个最小值来到栈顶。

解法2:只使用1个栈,用一个变量min_val记录当前的最小值,将当前最小值一同入栈,为节省空间,仅在当前最小值更改时才入栈。所以该栈的push和pop实际上可能是两次。当新进来的数小于min_val时,把当前的min_val和新进来的数一起推入到栈,min_val变为这个新进来的数。当pop栈顶元素的时候,如果栈顶元素的值和min_val相等,那么就把它下面记录的之前最小值赋给min_val并弹出。

解法3:也是使用1个栈,但栈中存的是当前值与最小值的差,用一个元素来记录,然后根据这个值可以计算出当前值和最小值。当栈顶元素为正时,表示当前元素比最小元素大,当前值为最小值+差值;当栈顶元素为负时,其表示的是当前元素值比之前最小值小,现在的最小值就是元素值。

要注意重复值的push和pop。

2Stack 

class MinStack(object):

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.stack = []     #建立了两个栈
        self.minStack = []
        

    def push(self, x):
        """
        :type x: int
        :rtype: None
        """
        self.stack.append(x)     #将得到 的数压入栈
        if len(self.minStack) == 0 or x <= self.minStack[-1]:  #如果最小栈为0 ,或者压入的数小于最小栈,就把这个数压入最小栈中
            self.minStack.append(x)
        

    def pop(self):
        """
        :rtype: None
        """
        if self.top() == self.getMin():   #如果栈顶元素和最小栈最后一个数相等
            self.minStack.pop()      #删除最小栈最后一个值
        return self.stack.pop()     
        

    def top(self):
        """
        :rtype: int
        """
        return self.stack[-1]      #返回栈最上边的一个数
        

    def getMin(self):
        """
        :rtype: int
        """
        return self.minStack[-1]    #调用这个函数救就会将最小栈最后一个数返回
        


# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()

 1Stack,最小值和元素一同入栈

class MinStack(object):

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.min = 2147483647
        self.stack = []     #建立了一个栈
        

    def push(self, x):
        """
        :type x: int
        :rtype: None
        """
        if x <= self.min:  #如果要压入的元素小于等于最小值,就将最小值压入栈;
            self.stack.append(self.min)
            self.min = x           #min变为一个更小的值
        self.stack.append(x)   #否则将x压入栈中
        

    def pop(self):
        """
        :rtype: None
        """
        peak = self.stack.pop()          #将栈中元素取出,赋值给peak,如果peak等于最小值,将取出的值赋值给最小值
        if peak == self.min:    #减产删除的元素是不是最小值,如果是的话,就将下一个数重新命名为最小值。
            self.min = self.stack.pop()   #
        

    def top(self):
        """
        :rtype: int
        """
        return self.stack[-1]          #返回栈的最后一个元素
        

    def getMin(self):
        """
        :rtype: int
        """
        return self.min     #返回最小值
        


# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()

232. Implement Queue using Stacks  使用堆栈实现队列(Easy)

Implement the following operations of a queue using stacks.

  • push(x) -- Push element x to the back of queue.
  • pop() -- Removes the element from in front of queue.
  • peek() -- Get the front element.
  • empty() -- Return whether the queue is empty.

Example:

MyQueue queue = new MyQueue();

queue.push(1);
queue.push(2);  
queue.peek();  // returns 1
queue.pop();   // returns 1
queue.empty(); // returns false

Notes:

  • You must use only standard operations of a stack -- which means only push to toppeek/pop from topsize, and is empty operations are valid.
  • Depending on your language, stack may not be supported natively. You may simulate a stack by using a list or deque (double-ended queue), as long as you use only standard operations of a stack.
  • You may assume that all operations are valid (for example, no pop or peek operations will be called on an empty queue).

用栈来实现队列,对比类似题目225. Implement Stack using Queues是反过来用。

class MyQueue(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.A = []   #建立两个栈
        self.B = []
        
        

    def push(self, x):
        """
        Push element x to the back of queue.
        :type x: int
        :rtype: None
        """
        self.A.append(x)    #将x压入栈中
        

    def pop(self):
        """
        Removes the element from in front of queue and returns that element.
        :rtype: int
        """
        self.peek()  #将栈A的值放在栈B中,然后删除最上边的元素,就是删除了队列最前边的元素
        return self.B.pop()     #返回删除上边元素的栈B
        

    def peek(self):
        """
        Get the front element.
        :rtype: int
        """
        if not self.B:      #如果B为空,当栈A不为空时,将栈A取出的元素加在B中;相当于调转一下位置,这样最下边的元素就成了最上边的元素。
            while self.A:
                self.B.append(self.A.pop())
        return self.B[-1]          #返回B最上边的值
        

    def empty(self):       
        """
        Returns whether the queue is empty.
        :rtype: bool
        """
        return not self.A and not self.B   
        


# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

225. Implement Stack using Queues  用队列实现栈 (Easy)

Implement the following operations of a stack using queues.

  • push(x) -- Push element x onto stack.
  • pop() -- Removes the element on top of the stack.
  • top() -- Get the top element.
  • empty() -- Return whether the stack is empty.

Example:

MyStack stack = new MyStack();

stack.push(1);
stack.push(2);  
stack.top();   // returns 2
stack.pop();   // returns 2
stack.empty(); // returns false

Notes:

  • You must use only standard operations of a queue -- which means only push to backpeek/pop from frontsize, and is empty operations are valid.
  • Depending on your language, queue may not be supported natively. You may simulate a queue by using a list or deque (double-ended queue), as long as you use only standard operations of a queue.
  • You may assume that all operations are valid (for example, no pop or top operations will be called on an empty stack).

用队列Queues的基本操作来实现栈Stack,队列和栈都是重要的数据结构,区别主要是,队列是先进先出,而栈是先进后出。

解法1:  在队列push进来新元素时,就把其它元素pop出来排到新元素的后面,新元素就在前面了,就可以后进先出。就好像大家都在排队,来了个重要客人,要让他第一,其他人从前面按顺序跑到他后面。

解法2: push的时候,其他元素不动只是用一个变量记住这个新元素。当top的时候直接给这个变量的值。当pop时,在调整顺序,把最后一个排到前面,弹出。变量记住目前在最尾部的值。


class MyStack(object):

    def __init__(self):
        self._queue = collections.deque()   #利用collections模块建立一个deque的双向队列。

    def push(self, x):
        q = self._queue
        q.append(x)
        for _ in range(len(q) - 1):   #每压入一个数,都将前面的数字转移到队列的后边。因为是空列表所以这样做有效,如果一开始是非空列表就不管用了
            q.append(q.popleft())    #popleft(获取最左边一个元素,并在队列中删除),然后加在q中。
        
    def pop(self):
        return self._queue.popleft()

    def top(self):
        return self._queue[0]
    
    def empty(self):
        return not len(self._queue)


# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()

224. Basic Calculator  基本计算器 (Hard)

Implement a basic calculator to evaluate a simple expression string.

The expression string may contain open ( and closing parentheses ), the plus + or minus sign -non-negative integers and empty spaces .

Example 1:

Input: "1 + 1"
Output: 2

Example 2:

Input: " 2-1 + 2 "
Output: 3

Example 3:

Input: "(1+(4+5+2)-3)+(6+8)"
Output: 23

Note:

  • You may assume that the given expression is always valid.
  • Do not use the eval built-in library function. 

参考链接:https://blog.csdn.net/fuxuemingzhu/article/details/84133441 

这个题没有乘除法,也就少了计算优先级的判断了。众所周知,实现计算器需要使用一个栈,来保存之前的结果,把后面的结果计算出来之后,和栈里的数字进行操作。

使用了res表示不包括栈里数字在内的结果,num表示当前操作的数字,sign表示运算符的正负,用栈保存遇到括号时前面计算好了的结果和运算符。

操作的步骤是:

如果当前是数字,那么更新计算当前数字;
如果当前是操作符+或者-,那么需要更新计算当前计算的结果res,并把当前数字num设为0,sign设为正负,重新开始;
如果当前是(,那么说明后面的小括号里的内容需要优先计算,所以要把res,sign进栈,更新res和sign为新的开始;
如果当前是),那么说明当前括号里的内容已经计算完毕,所以要把之前的结果出栈,然后计算整个式子的结果;
最后,当所有数字结束的时候,需要把结果进行计算,确保结果是正确的。
 

class Solution(object):
    def calculate(self, s):
        """
        :type s: str
        :rtype: int
        """
        res, num, sign = 0, 0, 1     #res表示不包括栈里数字在内的结果;num表示当前操作的数字;sign表示运算符的正负;
        stack = []          #用栈保存遇到括号是前面计算好了的结果和运算符;
        for c in s:
            if c.isdigit():
                num = 10 * num + int(c)
            elif c == "+" or c == "-":
                res = res + sign * num
                num = 0
                sign = 1 if c == "+" else -1
            elif c == "(":
                stack.append(res)
                stack.append(sign)
                res = 0
                sign = 1
            elif c == ")":
                res = res + sign * num
                num = 0
                res *= stack.pop()
                res += stack.pop()
        res = res + sign * num
        return res

227. Basic Calculator II  基本计算器II  (Medium)

Implement a basic calculator to evaluate a simple expression string.

The expression string contains only non-negative integers, +-*/ operators and empty spaces . The integer division should truncate toward zero.

Example 1:

Input: "3+2*2"
Output: 7

Example 2:

Input: " 3/2 "
Output: 1

Example 3:

Input: " 3+5 / 2 "
Output: 5

Note:

  • You may assume that the given expression is always valid.
  • Do not use the eval built-in library function.

直接使用eval可以过。。然后算法的话,使用下下面的方法:

用num保存上一个数字,用pre_op保存上一个操作符。当遇到新的操作符的时候,需要根据pre_op进行操作。乘除的优先级高于加减。所以有以下规则:

之前的运算符是+,那么需要把之前的数字num进栈,然后等待下一个操作数的到来。 
之前的运算符是-,那么需要把之前的数字求反-num进栈,然后等待下一个操作数的到来。 
之前的运算符是×,那么需要立刻出栈和之前的数字相乘,重新进栈,然后等待下一个操作数的到来。 
之前的运算符是/,那么需要立刻出栈和之前的数字相除,重新进栈,然后等待下一个操作数的到来。

注意比较的都是之前的操作符和操作数,现在遇到的操作符是没有什么用的。

另外,坑爹的Python地板除。。比如-3//2=2的,和c++不一样。因此真正操作的时候如果遇到负数,使用的用浮点除再取整的方式获得和c++一样的结果。
原文:https://blog.csdn.net/fuxuemingzhu/article/details/80826333 
 

class Solution(object):
    def calculate(self, s):
        """
        :type s: str
        :rtype: int
        """
        stack = []
        pre_op = '+'             #保存操作符
        num = 0
        for i, each in enumerate(s):   #enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
            if each.isdigit():
                num = 10 * num + int(each)
            if i == len(s) - 1 or each in '+-*/':
                if pre_op == '+':
                    stack.append(num)
                elif pre_op == '-':
                    stack.append(-num)
                elif pre_op == '*':
                    stack.append(stack.pop() * num)
                elif pre_op == '/':
                    top = stack.pop()
                    if top < 0:
                        stack.append(int(top / num))
                    else:
                        stack.append(top // num)
                pre_op = each
                num = 0
        return sum(stack)

直接使用eval可以过。。然后算法的话,使用下下面的方法:

用num保存上一个数字,用pre_op保存上一个操作符。当遇到新的操作符的时候,需要根据pre_op进行操作。乘除的优先级高于加减。所以有以下规则:

之前的运算符是+,那么需要把之前的数字num进栈,然后等待下一个操作数的到来。 
之前的运算符是-,那么需要把之前的数字求反-num进栈,然后等待下一个操作数的到来。 
之前的运算符是×,那么需要立刻出栈和之前的数字相乘,重新进栈,然后等待下一个操作数的到来。 
之前的运算符是/,那么需要立刻出栈和之前的数字相除,重新进栈,然后等待下一个操作数的到来。

注意比较的都是之前的操作符和操作数,现在遇到的操作符是没有什么用的。

另外,坑爹的Python地板除。。比如-3//2=2的,和c++不一样。因此真正操作的时候如果遇到负数,使用的用浮点除再取整的方式获得和c++一样的结果。
原文:https://blog.csdn.net/fuxuemingzhu/article/details/80826333 
 

class Solution(object):
    def calculate(self, s):
        """
        :type s: str
        :rtype: int
        """
        stack = []
        pre_op = '+'             #保存操作符
        num = 0
        for i, each in enumerate(s):   #enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
            if each.isdigit():
                num = 10 * num + int(each)
            if i == len(s) - 1 or each in '+-*/':
                if pre_op == '+':
                    stack.append(num)
                elif pre_op == '-':
                    stack.append(-num)
                elif pre_op == '*':
                    stack.append(stack.pop() * num)
                elif pre_op == '/':
                    top = stack.pop()
                    if top < 0:
                        stack.append((-1) * int((-1) * top / num))
                    else:
                        stack.append(top // num)
                pre_op = each
                num = 0
        return sum(stack)

42. Trapping Rain Water  收集雨水 (Hard)

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.


The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!

Example:

Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6

解法1:双指针Two Pointers,left和right分别指向数组的头尾,从两边向中间扫描,在当前两指针的范围内,先比较两头找出较小值,如果较小值是left指向的值,则从左向右扫描,如果较小值是right指向的值,则从右向左扫描,若遇到的值比当较小值小,则将差值存入结果,如遇到的值大,则重新确定新的窗口范围,迭代直至left和right指针重合。

对于任何一个坐标,检查其左右的最大坐标,然后相减就是容积。所以, 
1. 从左往右扫描一遍,对于每一个坐标,求取左边最大值。
2. 从右往左扫描一遍,对于每一个坐标,求最大右值。
3. 再扫描一遍,求取容积并加和。
2和3可以合并成一个循环,公式:H[i] = min(Max(Array[j] ),  Max(Array[k])) – Array[i]  where  j < i and k > i

解法2:栈stack

Follow up:

不求所有容积,而是求容积中的最大值。这样就类似于Container With Most Water,但是有不同的地方,这题里面每一个坐标本身是占体积的。所以从两边往中间扫的时候,根本不知道中间坐标共占用了多少体积。

来源:http://www.cnblogs.com/lightwindy/p/8495692.html

class Solution(object):
    def trap(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        if not A:  #A为空,返回0
            return 0
        res = 0
        left, right = 0, len(A) - 1  #双指针法
        left_max, right_max = 0, 0
        while left < right:     
            if A[left] < A[right]:       #如果左端的值小于右端的值
                left_max = max(left_max, A[left])
                left += 1       #左边的指针向右移一个长度
                res += max(0, left_max - A[left])    #左边的指针移了一个长度的数值减去之前位置的数值,和0 比较
            else:
                right_max = max(right_max, A[right])
                right -= 1
                res += max(0, right_max - A[right])
                 
        return res 
class Solution(object):
    def trap(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        result = 0
        stack = []
 
        for i in xrange(len(A)):
            mid_height = 0
            while stack:
                [pos, height] = stack.pop()
                result += (min(height, A[i]) - mid_height) * (i - pos - 1)
                mid_height = height
 
                if A[i] < height:
                    stack.append([pos, height])
                    break
            stack.append([i, A[i]])
 
        return result

107. Binary Tree Level Order Traversal II   二叉树层序遍历 II (Easy)

Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root).

For example:
Given binary tree [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

 

return its bottom-up level order traversal as:

[
  [15,7],
  [9,20],
  [3]
]

102题的变形只是最后输出的顺序变了,这题是从最后一层开始。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def levelOrderBottom(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if root is None:   #根节点如果为空,则返回空列表
            return []
 
        result, current = [], [root]   #
        while current:   #若这个列表不为空,就一直循环
            next_level, vals = [], []    
            for node in current:
                vals.append(node.val)
                if node.left:
                    next_level.append(node.left)
                if node.right:
                    next_level.append(node.right)
            current = next_level
            result.append(vals)   #加的时候不是一个一个加,是把上一个列表的值一块加到新的列表中。
 
        return result[::-1]   #将列表中的元素倒着输出

102. Binary Tree Level Order Traversal  二叉树层序遍历 (Medium)

Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).

For example:
Given binary tree [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

 

return its level order traversal as:

[
  [3],
  [9,20],
  [15,7]
]

给一棵二叉树,返回从左往右层序遍历的结果,每一层单独记录。有BFS(迭代Iteration)和DFS(递归Recursion)两种解法。

拓展:先序遍历preorder的递归做法加上一个层就是这题的DFS解法。


#迭代法
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):    
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if root is None:
            return []
        result, current = [], [root]
        while current:
            next_level, vals = [], []
            for node in current:
                vals.append(node.val)
                if node.left:
                    next_level.append(node.left)
                if node.right:
                    next_level.append(node.right)
            current = next_level
            result.append(vals)
        return result

 #递归法

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):   
    def preorder(self, root, level, res):
        if root:
            if len(res) < level+1: res.append([])
            res[level].append(root.val)
            self.preorder(root.left, level+1, res)
            self.preorder(root.right, level+1, res)
 
    def levelOrder(self, root):
        res=[]
        self.preorder(root, 0, res)
        return res

496. Next Greater Element I   下一个较大元素  I (Easy)

You are given two arrays (without duplicates) nums1 and nums2 where nums1’s elements are subset of nums2. Find all the next greater numbers for nums1's elements in the corresponding places of nums2.

The Next Greater Number of a number x in nums1 is the first greater number to its right in nums2. If it does not exist, output -1 for this number.

Example 1:

Input: nums1 = [4,1,2], nums2 = [1,3,4,2].
Output: [-1,3,-1]
Explanation:
    For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1.
    For number 1 in the first array, the next greater number for it in the second array is 3.
    For number 2 in the first array, there is no next greater number for it in the second array, so output -1.

Example 2:

Input: nums1 = [2,4], nums2 = [1,2,3,4].
Output: [3,-1]
Explanation:
    For number 2 in the first array, the next greater number for it in the second array is 3.
    For number 4 in the first array, there is no next greater number for it in the second array, so output -1.

Note:

  1. All elements in nums1 and nums2 are unique.

  2. The length of both nums1 and nums2 would not exceed 1000.

解法:栈,递减栈。先求出nums2中所有元素的右边第一个较大数字的位置,并记录到map中。然后,因为nums1是子数组,循环nums1中的元素,记录在map中值并返回。求nums2中下一个较大元素时用递减栈,循环元素,当前元素大于栈顶元素时,就弹出栈顶元素,并记录栈顶元素下一个最大就是当前元素。然后继续比较栈顶元素,直到小于或等于栈顶元素。

G家followup: 如果data是stream data怎么改代码和设计输出。

class Solution(object):
    def nextGreaterElement(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        d = {}    #建立一个字典,两个列表
        st = []     
        ans = []   #存放最后的结果
         
        for x in nums2:       #遍历列表2
            while len(st) and st[-1] < x:     #这个存在意义就是将前一个小一点的数和后一个大一点的数组成字典,如果后一个数比前一个小就不组成字典。
                d[st.pop()] = x
            st.append(x)
 
        for x in nums1:
            ans.append(d.get(x, -1))   #字典(Dictionary) get() 函数返回指定键的值,如果值不在字典中返回默认值。组成字典。
             
        return ans

346.Moving Average fromData Stream 从数据流中移动平均值(Easy)

Given a stream of integers and a window size, calculate the moving average of all integers in the sliding window.

For example,
MovingAverage m = new MovingAverage(3);
m.next(1) = 1
m.next(10) = (1 + 10) / 2
m.next(3) = (1 + 10 + 3) / 3
m.next(5) = (10 + 3 + 5) / 3

给一个整数流和一个窗口,计算在给定大小的窗口里的数字的平均值。

解法:队列queue,用一个queue记录进入窗口的整数。当流进窗口的整数不足时,计算所有窗口内的数字和返回,当进入窗口的整数多于窗口大小时,移除最先进入窗口的整数,新的整数进入queue,然后计算窗口内的整数和。

# Time:  O(1)
# Space: O(w)
from collections import deque
 
class MovingAverage(object):
    def __init__(self, size):
        """
        Initialize your data structure here.
        :type size: int
        """
        self.__size = size
        self.__sum = 0
        self.__q = deque([])
 
    def next(self, val):
        """
        :type val: int
        :rtype: float
        """
        if len(self.__q) == self.__size:
            self.__sum -= self.__q.popleft()
        self.__sum += val
        self.__q.append(val)
        return 1.0 * self.__sum / len(self.__q)
 
 
# Your MovingAverage object will be instantiated and called as such:
# obj = MovingAverage(size)
# param_1 = obj.next(val) 

933. Number of Recent Calls  最近的通话数 (Easy)

Write a class RecentCounter to count recent requests.

It has only one method: ping(int t), where t represents some time in milliseconds.

Return the number of pings that have been made from 3000 milliseconds ago until now.

Any ping with time in [t - 3000, t] will count, including the current ping.

It is guaranteed that every call to ping uses a strictly larger value of t than before.

Example 1:

Input: inputs = ["RecentCounter","ping","ping","ping","ping"], inputs = [[],[1],[100],[3001],[3002]]
Output: [null,1,2,3,3]

Note:

  1. Each test case will have at most 10000 calls to ping.
  2. Each test case will call ping with strictly increasing values of t.
  3. Each call to ping will have 1 <= t <= 10^9.

使用一个队列,当t时间到达之后,在t-3000之前的调用全部删除,因为这些不会对后面的产生任何影响了。删除之后,求长度就好了。

class RecentCounter(object):

    def __init__(self):
        self.que = collections.deque()

    def ping(self, t):
        """
        :type t: int
        :rtype: int
        """
        while self.que and self.que[0] < t - 3000:
            self.que.popleft()
        self.que.append(t)
        return len(self.que)


# Your RecentCounter object will be instantiated and called as such:
# obj = RecentCounter()
# param_1 = obj.ping(t)

103. Binary Tree Zigzag Level Order Traversal  二叉树之字形层序遍历 (Medium)

Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).

For example:
Given binary tree [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

return its zigzag level order traversal as:

[
  [3],
  [20,9],
  [15,7]
]

102题的变形,不同之处在于一行是从左到右遍历,下一行是从右往左遍历,交叉往返的之字形的层序遍历。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def zigzagLevelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if root is None:    #如果根节点为空,则返回一个空列表
            return []
        result, current, level = [], [root], 1             
        while current:      #根不为空就一直循环
            next_level, vals = [], []     
            for node in current:
                vals.append(node.val)
                if node.left:
                    next_level.append(node.left)
                if node.right:
                    next_level.append(node.right)
            if level % 2:
                result.append(vals)
            else:
                result.append(vals[::-1])
            level += 1
            current = next_level
        return result

331. Verify Preorder Serialization of a Binary Tree  验证二叉树的前序序列  (Meidum)

One way to serialize a binary tree is to use pre-order traversal. When we encounter a non-null node, we record the node's value. If it is a null node, we record using a sentinel value such as #.

     _9_
    /   \
   3     2
  / \   / \
 4   1  #  6
/ \ / \   / \
# # # #   # #

For example, the above binary tree can be serialized to the string "9,3,4,#,#,1,#,#,2,#,6,#,#", where # represents a null node.

Given a string of comma separated values, verify whether it is a correct preorder traversal serialization of a binary tree. Find an algorithm without reconstructing the tree.

Each comma separated value in the string must be either an integer or a character '#'representing null pointer.

You may assume that the input format is always valid, for example it could never contain two consecutive commas such as "1,,3".

Example 1:

Input: 
"9,3,4,#,#,1,#,#,2,#,6,#,#"
Output: 

true

Example 2:

Input: 
"1,#"
Output: 

false

Example 3:

Input: 
"9,#,#,1"
Output: 

false

给了一个先序遍历,判断能不能构成合法的二叉树。这个字符串中,#表示空节点。

判断一个二叉树是否合法的情况,那么应该是个递归或者循环问题。那么解决问题的思路是从顶部向下分析还是从底下向顶部分析呢?正确的结果应该是从二叉树的底部向上进行分析,因为我们可以通过#号判断是否是空节点,然后判断最底下的叶子节点是否含有两个空孩子的方式,循环向上解决这个问题。

所以这个题的思路就很明了了:用一个栈,从字符串的左侧向右依次进栈,如果满足栈的后三位是数字,#,#的模式时,说明可以构成合法的叶子节点,把这个叶子节点换成#号,代表空节点,然后继续遍历。最后应该只剩下一个#,那么就是一个合法的二叉树。

如:”9,3,4,#,#,1,#,#,2,#,6,#,#” 遇到x # #的时候,就把它变为 #

模拟一遍过程:

9,3,4,#,# => 9,3,# 继续读
9,3,#,1,#,# => 9,3,#,# => 9,# 继续读
9,#2,#,6,#,# => 9,#,2,#,# => 9,#,# => #

原文:https://blog.csdn.net/fuxuemingzhu/article/details/79537797 

class Solution(object):
    def isValidSerialization(self, preorder):
        """
        :type preorder: str
        :rtype: bool
        """
        stack = []
        for node in preorder.split(','):       #将这个字符串以逗号作为区分,每一个点循环一次
            stack.append(node)       #将这个点加入栈中
            while len(stack) >= 3 and stack[-1] == stack[-2] == '#' and stack[-3] != '#':        #当这个栈的长度大于等于3且栈的最后一位和倒数第二位是井号,倒数第三位是数字
                stack.pop(), stack.pop(), stack.pop()        #就将这三个数字取出删除
                stack.append('#')      #将井号压入栈中
        return len(stack) == 1 and stack.pop() == '#'    #如果栈的长度为1且将最后一个字符取出为井号,则说明为真

946. Validate Stack Sequences  验证栈序列  (Medium)

Given two sequences pushed and popped with distinct values, return true if and only if this could have been the result of a sequence of push and pop operations on an initially empty stack.

Example 1:

Input: pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
Output: true
Explanation: We might do the following sequence:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1

Example 2:

Input: pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
Output: false
Explanation: 1 cannot be popped before 2.

Note:

  1. 0 <= pushed.length == popped.length <= 1000
  2. 0 <= pushed[i], popped[i] < 1000
  3. pushed is a permutation of popped.
  4. pushed and popped have distinct values.

给出了一个栈的输入数字,按照这个顺序输入到栈里,能不能得到一个对应的栈的输出序列。

我使用的方法异常简单粗暴,直接模拟这个过程。

题目已知所有的数字都是不同的。我们在模拟这个弹出的过程中,进行一个判断,如果这个弹出的数字和栈顶数字是吻合的,那么栈就要把已有的数字弹出来。如果栈是空的,或者栈顶数字和弹出的数字不等,那么我们应该把pushed数字一直往里放,直到相等为止。

最后,如果栈的入栈序列能得到这个出栈序列,那么栈应该是空的。
原文:https://blog.csdn.net/fuxuemingzhu/article/details/84495797 
 

class Solution(object):
    def validateStackSequences(self, pushed, popped):
        """
        :type pushed: List[int]
        :type popped: List[int]
        :rtype: bool
        """
        stack = []      #建立一个空栈
        N = len(pushed)    
        pi = 0
        for i in range(N):
            if stack and popped[i] == stack[-1]:     #如果栈为真且要删除的第一个元素和栈顶元素相等,就将栈中元素删除
                stack.pop()
            else:     #否则
                while pi < N and pushed[pi] != popped[i]:
                    stack.append(pushed[pi])
                    pi += 1
                pi += 1
        return not stack

310. Minimum Height Trees  最小高度树 (Medium)

For an undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels.

Format
The graph contains n nodes which are labeled from 0 to n - 1. You will be given the number n and a list of undirected edges (each edge is a pair of labels).

You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges.

Example 1 :

Input:
n = 4
,
edges = [[1, 0], [1, 2], [1, 3]]
0
        |
        1
       / \
      2   3 

Output:
[1]

Example 2 :

Input:
n = 6
,
edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]]
0  1  2
      \ | /
        3
        |
        4
        |
        5 

Output:
[3, 4]

Note:

  • According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.”
  • The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf.
class Solution(object):
    def findMinHeightTrees(self, n, edges):
        """
        :type n: int
        :type edges: List[List[int]]
        :rtype: List[int]
        """
        if n == 1:
            return [0]
 
        neighbors = collections.defaultdict(set)
        for u, v in edges:
            neighbors[u].add(v)
            neighbors[v].add(u)
 
        pre_level, unvisited = [], set()
        for i in xrange(n):
            if len(neighbors[i]) == 1:  # A leaf.
                pre_level.append(i)
            unvisited.add(i)
 
        # A graph can have 2 MHTs at most.
        # BFS from the leaves until the number
        # of the unvisited nodes is less than 3.
        while len(unvisited) > 2:
            cur_level = []
            for u in pre_level:
                unvisited.remove(u)
                for v in neighbors[u]:
                    if v in unvisited:
                        neighbors[v].remove(u)
                        if len(neighbors[v]) == 1:
                            cur_level.append(v)
            pre_level = cur_level
 
        return list(unvisited)

279. Perfect Squares 完美平方  (Medium)

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.

Example 1:

Input: n =
12
Output: 3 
Explanation: 

12 = 4 + 4 + 4.

Example 2:

Input: n =
13
Output: 2
Explanation: 

13 = 4 + 9.

 

class Solution(object):
    def numSquares(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n < 2:
            return n
        lst = []
        i = 1
        while i * i <= n:
            lst.append( i * i )
            i += 1
        cnt = 0
        toCheck = {n}
        while toCheck:
            cnt += 1
            temp = set()
            for x in toCheck:
                for y in lst:
                    if x == y:
                        return cnt
                    if x < y:
                        break
                    temp.add(x-y)
            toCheck = temp

        return cnt

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(数据结构,python,算法)