• 九章算法班ladder题目梳理


    1 - 从strStr谈面试技巧与代码风格


     

    13.字符串查找

    如果target在source中,返回起始下标,否则返回-1

    要点:该题O(mn)可过,两层循环即可。

    class Solution:
        def strStr(self, source, target):
            # write your code here
            if source is None or target is None:
                return -1
            if target == '':
                return 0
            for i in range(len(source)):
                m = i
                n = 0
                while m < len(source) and source[m] == target[n]:
                    if n == len(target) - 1:
                        return i
                    m += 1
                    n += 1
            return -1
    

    17.4.7二刷

    class Solution:
        def strStr(self, source, target):
            # write your code here
            if source is None or target is None:
                return -1
            if not target:
                return 0
                
            for i in range(len(source) - len(target) + 1):
                for j in range(len(target)):
                    if source[i + j] != target[j]:
                        break
                    if j == len(target) - 1:
                        return i
            return -1
    

    -------------------------------------------------------------------------

    17.子集

    返回一个整数list的所有子集。

    要点:某些地方注意使用[:]做拷贝。

    class Solution:
        """
        @param S: The set of numbers.
        @return: A list of lists. See example.
        """
        def subsets(self, S):
            # write your code here
            results = []
            if not S:
                return results
            S.sort()
            self.dfsHelper(S, 0, [], results)
            return results
    
        def dfsHelper(self, S, startnum, subset, results):
            results.append(subset[:])
            for i in range(startnum, len(S)):
                subset.append(S[i])
                self.dfsHelper(S, i + 1, subset, results)
                subset.pop()

    17.4.7二刷

    class Solution:
        """
        @param S: The set of numbers.
        @return: A list of lists. See example.
        """
        def subsets(self, S):
            # write your code here
            result = []
            S.sort()
            self.helper(S, 0, [], result)
            return result
            
        def helper(self, S, start, subset, result):
            result.append(subset[:])
            for i in range(start, len(S)):
                subset.append(S[i])
                self.helper(S, i + 1, subset, result)
                subset.pop()
    

    -------------------------------------------------------------------------

    18.带重复元素的子集

    给定一个可能具有重复数字的列表,返回其所有可能的子集(子集不能重复)。

    要点:选代表,当存在重复元素时,必须前一个元素在子集中,后一个元素才能加入子集。

    class Solution:
        """
        @param S: A set of numbers.
        @return: A list of lists. All valid subsets.
        """
        def subsetsWithDup(self, S):
            # write your code here
            results = []
            if not S:
                return results
            S.sort()
            self.dfsHelper(S, 0, [], results)
            return results
    
        def dfsHelper(self, S, start_index, subset, results):
            results.append(subset[:])
            for i in range(start_index, len(S)):
                if i != start_index and subset.count(S[i]) != i - S.index(S[i]):
                    continue
                subset.append(S[i])
                self.dfsHelper(S, i + 1, subset, results)
                subset.pop()

    17.4.7二刷

    class Solution:
        """
        @param S: A set of numbers.
        @return: A list of lists. All valid subsets.
        """
        def subsetsWithDup(self, S):
            # write your code here
            results = []
            S.sort()
            self.helper(S, 0, [], results)
            return results
    
        def helper(self, S, start_index, subset, results):
            results.append(subset[:])
            for i in range(start_index, len(S)):
                # 注意下面这个写法
                if i != start_index and S[i] == S[i - 1]:
                    continue
                subset.append(S[i])
                self.helper(S, i + 1, subset, results)
                subset.pop()
    

    -------------------------------------------------------------------------

    15.全排列

    给定一个数字列表,返回其所有可能的排列。没有重复数字。

    要点:要合理使用切片,二刷记得优化

    class Solution:
        """
        @param nums: A list of Integers.
        @return: A list of permutations.
        """
        def permute(self, nums):
            # write your code here
            results = []
            if nums is None:
                return results
            nums.sort()
            self.dfsHelper(nums[:], [], results, len(nums))
            return results
    
        def dfsHelper(self, nums, subset, results, length):
            if len(subset) == length:
                results.append(subset[:])
                return
            for i in range(len(nums)):
                subset.append(nums[i])
                self.dfsHelper(nums[:i] + nums[i + 1:], subset, results, length)
                subset.pop()
    

    17.4.7二刷,使用set避免大量切片,set删除指定元素O(1)

    class Solution:
        """
        @param nums: A list of Integers.
        @return: A list of permutations.
        """
        def permute(self, nums):
            # write your code here
            result = []
            self.helper(nums, result, [], set(range(len(nums))))
            return result
    
        def helper(self, nums, result, subsequence, not_visited):
            if not not_visited:
                result.append(subsequence[:])
                return
            for index in not_visited:
                subsequence.append(nums[index])
                not_visited.remove(index)
                self.helper(nums, result, subsequence, not_visited)
                not_visited.add(index)
                subsequence.pop()
    

      

    -------------------------------------------------------------------------

    16.带重复元素的排列

    给出一个具有重复数字的列表,找出列表所有不同的排列。

    要点:选代表。重复元素中,后面的进入subset的前提是前面的都在subset中。

    class Solution:
        """
        @param nums: A list of integers.
        @return: A list of unique permutations.
        """
        def permuteUnique(self, nums):
            # write your code here
            results = []
            if nums is None:
                return results
            nums.sort()
            self.dfsHelper(nums[:], [], results, nums)
            return results
    
        def dfsHelper(self, nums, subset, results, S):
            if len(subset) == len(S):
                results.append(subset[:])
                return
            for i in range(len(nums)):
                if nums.count(nums[i]) > 1 and nums.index(nums[i]) != i:
                    continue
                subset.append(nums[i])
                self.dfsHelper(nums[:i] + nums[i + 1:], subset, results, S)
                subset.pop()
    

    17.4.7二刷

    class Solution:
        """
        @param nums: A list of integers.
        @return: A list of unique permutations.
        """
        def permuteUnique(self, nums):
            # write your code here
            result = []
            nums.sort()
            self.helper(nums, result, [], set(range(len(nums))))
            return result
    
        def helper(self, nums, result, subsequence, not_visited):
            if not not_visited:
                result.append(subsequence[:])
                return
            for index in not_visited:
                if index != 0 and nums[index] == nums[index - 1] 
                    and (index - 1) in not_visited:
                    continue
                subsequence.append(nums[index])
                not_visited.remove(index)
                self.helper(nums, result, subsequence, not_visited)
                not_visited.add(index)
                subsequence.pop()
    

      

    -------------------------------------------------------------------------

    594.strStr II 

    如果target在source中,返回起始下标,否则返回-1,要求时间复杂度O(m + n)

    要点:使用Rabin Karp,维护hash滑动窗口,计算原串各个子串hash值,然后与目标串hash值比较。

    注意1、整形越界。2、减法可能导致负数。3、double check

    class Solution:
        # @param {string} source a source string
        # @param {string} target a target string
        # @return {int} an integer as index
        def strStr2(self, source, target):
            # Write your code here
            BASE = 1000000
            if source is None or target is None:
                return -1
            if target == '':
                return 0
    
            power = 1
            for i in range(len(target) - 1):
                power = (power * 31) % BASE
    
            targetHashCode = 0
            for i in range(len(target)):
                targetHashCode = (targetHashCode * 31 + ord(target[i])) % BASE
    
            sourceHashCode = 0
            for i in range(len(source)):
                if i < len(target):
                    sourceHashCode = (sourceHashCode * 31 + ord(source[i])) % BASE
                else:
                    toMinus = ord(source[i - len(target)]) * power
                    sourceHashCode = (sourceHashCode - toMinus) % BASE
                    sourceHashCode = (sourceHashCode * 31 + ord(source[i])) % BASE
                    if sourceHashCode < 0:
                        sourceHashCode = (sourceHashCode + BASE) % BASE
    
                if i >= len(target) - 1 and sourceHashCode == targetHashCode:
                    n = 0
                    while source[n + i - len(target) + 1] == target[n]:
                        if n == len(target) - 1:
                            return i - len(target) + 1
                        n += 1
            return -1
    

    17.4.7二刷

    class Solution:
        # @param {string} source a source string
        # @param {string} target a target string
        # @return {int} an integer as index
        def strStr2(self, source, target):
            # Write your code here
            BASE = 1000000
            if source is None or target is None:
                return -1
            if not target:
                return 0
                
            m, n = len(source), len(target)
            
            # power
            power = 1
            for i in range(n):
                power = (power * 31) % BASE
            
            # target hash code    
            target_code = 0
            for i in range(n):
                target_code = (target_code * 31 + ord(target[i])) % BASE
            
            # source hash code    
            source_code = 0
            for i in range(m):
                # abc + d
                source_code = (source_code * 31 + ord(source[i])) % BASE
                if i < n - 1:
                    continue
                # abcd - a
                if i > n - 1:
                    source_code -= (ord(source[i - n]) * power) % BASE
                    if source_code < 0:
                        source_code += BASE
                # double check
                if source_code == target_code:
                    if source[i - n + 1: i + 1] == target:
                        return i - n + 1
            return -1
    

      

    2 - 二分法


    459.排序数组中最接近的元素

    在一个排好序的数组 A 中找到 i 使得 A[i] 最接近 target(存在重复元素时,可返回任意一个元素的下标)

    要点:按九章的二分写法,left和right在结束时停止在符合判断条件的分界线处,判断left和right哪个更接近即可。

    class Solution:
        # @param {int[]} A an integer array sorted in ascending order
        # @param {int} target an integer
        # @return {int} an integer
        def closestNumber(self, A, target):
            # Write your code here
            if not A or target is None:
                return -1
                
            left = 0
            right = len(A) - 1
            
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[mid] >= target:
                    right = mid
                else:
                    left = mid
                    
            if A[left] == target:
                return left
            elif A[right] == target:
                return right
            elif abs(A[left] - target) <= abs(A[right] - target):
                return left
            else:
                return right
    

    17.4.8二刷

    class Solution:
        # @param {int[]} A an integer array sorted in ascending order
        # @param {int} target an integer
        # @return {int} an integer
        def closestNumber(self, A, target):
            # Write your code here
            if not A or target is None:
                return -1
                
            left, right = 0, len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[mid] < target:
                    left = mid
                else:
                    right = mid
                    
            return left if abs(target - A[left]) < abs(target - A[right]) else right

    -------------------------------------------------------------------------

    458.目标最后位置

    给一个升序数组,找到target最后一次出现的位置,如果没出现过返回-1

    要点:OOXX经典问题,关键在于==mid时的判断

    class Solution:
        # @param {int[]} A an integer array sorted in ascending order
        # @param {int} target an integer
        # @return {int} an integer
        def lastPosition(self, A, target):
            # Write your code here
            if not A:
                return -1
            left = 0
            right = len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[mid] == target:
                    left = mid
                elif A[mid] < target:
                    left = mid
                else:
                    right = mid
            if A[right] == target:
                return right
            if A[left] == target:
                return left
            return -1
    

    17.4.8二刷

    class Solution:
        # @param {int[]} A an integer array sorted in ascending order
        # @param {int} target an integer
        # @return {int} an integer
        def lastPosition(self, A, target):
            # Write your code here
            if not A or target is None:
                return -1
                
            left, right = 0, len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[mid] <= target:
                    left = mid
                else:
                    right = mid
                    
            if A[right] == target:
                return right
            if A[left] == target:
                return left
                
            return -1
    

      

    -------------------------------------------------------------------------

    28.搜索二维矩阵

    写出一个高效的算法来搜索 m × n矩阵中的值。

    这个矩阵具有以下特性:

    • 每行中的整数从左到右是排序的。
    • 每行的第一个数大于上一行的最后一个整数。

    要点:一刷用了两次二分,二刷可以试试让元素比较右边和下边的元素。

    class Solution:
        """
        @param matrix, a list of lists of integers
        @param target, an integer
        @return a boolean, indicate whether matrix contains target
        """
        def searchMatrix(self, matrix, target):
            # write your code here
            if not matrix:
                return False
            m = len(matrix)
            n = len(matrix[0])
            if n == 0:
                return False
            left, right = 0, m - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if matrix[mid][0] < target:
                    left = mid
                elif matrix[mid][0] > target:
                    right = mid
                else:
                    return True
                    
            if matrix[right][0] <= target:
                row_num = right
            elif matrix[left][0] <= target:
                row_num = left
            elif left - 1 >= 0 and matrix[left][0] <= target:
                row_num = left - 1
            else:
                return False
                
            left, right = 0, n - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if matrix[row_num][mid] < target:
                    left = mid
                elif matrix[row_num][mid] > target:
                    right = mid
                else:
                    return True
            if matrix[row_num][left] == target or matrix[row_num][right] == target:
                return True
            return False
    

    17.4.8二刷

    class Solution:
        """
        @param matrix, a list of lists of integers
        @param target, an integer
        @return a boolean, indicate whether matrix contains target
        """
        def searchMatrix(self, matrix, target):
            # write your code here
            if not matrix or not matrix[0] or target is None:
                return False
                
            row = self.binSearch([a[0] for a in matrix], target)
            col = self.binSearch(matrix[row], target)
            
            if matrix[row][col] == target:
                return True
            return False
            
        def binSearch(self, A, target):
            left, right = 0, len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[mid] < target:
                    left = mid
                else:
                    right = mid
                    
            if A[right] <= target:
                return right
            else:
                return left
    

      

    -------------------------------------------------------------------------

    585.Maximum Number in Mountain Sequence

    Given a mountain sequence of n integers which increase firstly and then decrease, find the mountain top.

    要点:mid与左右两边比较,确定是上升的还是下降的

    class Solution:
        # @param {int[]} nums a mountain sequence which increase firstly and then decrease
        # @return {int} then mountain top
        def mountainSequence(self, nums):
            # Write your code here
            if len(nums) == 1:
                return nums[0]
            left = 0
            right = len(nums) - 1
            
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if nums[mid - 1] < nums[mid] and nums[mid] < nums[mid + 1]:
                    left = mid
                elif nums[mid - 1] > nums[mid] and nums[mid] > nums[mid + 1]:
                    right = mid
                else:
                    return nums[mid]
            return nums[left] if nums[left] > nums[right] else nums[right]
                    
    

    17.4.8二刷

    class Solution:
        # @param {int[]} nums a mountain sequence which increase firstly and then decrease
        # @return {int} then mountain top
        def mountainSequence(self, nums):
            # Write your code here
            left, right = 0, len(nums) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if nums[mid - 1] < nums[mid]:
                    left = mid
                else:
                    right = mid
                    
            if nums[right] > nums[left]:
                return nums[right]
            return nums[left]
    

      

    -------------------------------------------------------------------------

    447.在大数组中查找

    给一个按照升序排序的正整数数组。这个数组很大以至于你只能通过固定的接口 ArrayReader.get(k) 来访问第k个数。并且你也没有办法得知这个数组有多大。找到给出的整数target第一次出现的位置。你的算法需要在O(logk)的时间复杂度内完成,k为target第一次出现的位置的下标。如果找不到target,返回-1。

    要点:可认为整个数组是无限长,递增的。使用乘法增加的思想探测index>target的地方。

    """
    Definition of ArrayReader:
    class ArrayReader:
        def get(self, index):
            # this would return the number on the given index
            # return -1 if index is less than zero.
    """
    class Solution:
        # @param {ArrayReader} reader: An instance of ArrayReader 
        # @param {int} target an integer
        # @return {int} an integer
        def searchBigSortedArray(self, reader, target):
            # write your code here
            if not reader or not target:
                return -1
            
            index = 0
            while reader.get(index) < target:
                index = 2 * index + 1 
            
            left = 0
            right = index
            
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if reader.get(mid) >= target:
                    right = mid
                else:
                    left = mid
            
            if reader.get(left) == target:
                return left
            if reader.get(right) == target:
                return right    
            return -1
            
    

    17.4.8二刷

    """
    Definition of ArrayReader:
    class ArrayReader:
        def get(self, index):
            # this would return the number on the given index
            # return -1 if index is less than zero.
    """
    class Solution:
        # @param {ArrayReader} reader: An instance of ArrayReader 
        # @param {int} target an integer
        # @return {int} an integer
        def searchBigSortedArray(self, reader, target):
            # write your code here
            if not reader or target is None:
                return -1
                
            index = 1
            while reader.get(index) <= target:
                index *= 2
                
            left, right = 0, index
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if reader.get(mid) < target:
                    left = mid
                else:
                    right = mid
                    
            if reader.get(left) == target:
                return left
            if reader.get(right) == target:
                return right
                
            return -1
    

      

    -------------------------------------------------------------------------

    159.寻找旋转排序数组的最小值

    假设一个旋转排序的数组其起始位置是未知的(比如0 1 2 4 5 6 7 可能变成是4 5 6 7 0 1 2)。你需要找到其中最小的元素。你可以假设数组中不存在重复的元素。

    要点:mid的判断

    class Solution:
        # @param nums: a rotated sorted array
        # @return: the minimum number in the array
        def findMin(self, nums):
            # write your code here
            if not nums:
                return -1
                
            left = 0
            right = len(nums) - 1
            
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if nums[mid] < nums[right]:
                    right = mid
                elif nums[mid] > nums[right]:
                    left = mid
            return nums[left] if nums[left] < nums[right] else nums[right]
    

    17.4.9二刷

    class Solution:
        # @param nums: a rotated sorted array
        # @return: the minimum number in the array
        def findMin(self, nums):
            # write your code here
            left, right = 0, len(nums) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if nums[left] < nums[mid] < nums[right]:
                    return nums[left]
                elif nums[mid] < nums[right]:
                    right = mid
                else:
                    left = mid
                    
            if nums[left] < nums[right]:
                return nums[left]
            return nums[right]
    

      

    -------------------------------------------------------------------------

    75.寻找峰值

    你给出一个整数数组(size为n),其具有以下特点:

    • 相邻位置的数字是不同的      //数组不存在“平台”
    • A[0] < A[1] 并且 A[n - 2] > A[n - 1]   //至少存在一个峰

    假定P是峰值的位置则满足A[P] > A[P-1]A[P] > A[P+1],返回数组中任意一个峰值的位置。

    要点:根据mid是上升、下降、峰、谷分开判断

    class Solution:
        #@param A: An integers list.
        #@return: return any of peek positions.
        def findPeak(self, A):
            # write your code here
            if not A:
                return -1
            left = 0
            right = len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if mid - 1 < 0:
                    left = mid
                elif mid + 1 >= len(A):
                    right = mid
                elif A[mid - 1] < A[mid] and A[mid] < A[mid + 1]:
                    left = mid
                elif A[mid - 1] > A[mid] and A[mid] > A[mid + 1]:
                    right = mid
                elif A[mid - 1] > A[mid] and A[mid] < A[mid + 1]:
                    left = mid
                elif A[mid - 1] < A[mid] and A[mid] > A[mid + 1]:
                    return mid
                    
            if right - 1 >= 0 and right + 1 < len(A) 
                and A[right - 1] < A[right] and A[right] > A[right + 1]:
                return right
            else:
                return left
    

    17.4.8二刷

    class Solution:
        #@param A: An integers list.
        #@return: return any of peek positions.
        def findPeak(self, A):
            # write your code here
            left, right = 0, len(A) - 1
            while left - 1 < right:
                mid = (right - left) / 2 + left
                if A[mid - 1] < A[mid] < A[mid + 1]:
                    left = mid
                elif A[mid - 1] > A[mid] > A[mid + 1]:
                    right = mid
                elif A[mid - 1] > A[mid] < A[mid + 1]:
                    right = mid
                else:
                    return mid
    

      

    -------------------------------------------------------------------------

    74.第一个错误的代码版本

    代码库的版本号是从 1 到 n 的整数。某一天,有人提交了错误版本的代码,因此造成自身及之后版本的代码在单元测试中均出错。请找出第一个错误的版本号。

    要点:OOXX型找符合条件的最后一个

    #class SVNRepo:
    #    @classmethod
    #    def isBadVersion(cls, id)
    #        # Run unit tests to check whether verison `id` is a bad version
    #        # return true if unit tests passed else false.
    # You can use SVNRepo.isBadVersion(10) to check whether version 10 is a 
    # bad version.
    
    
    class Solution:
        """
        @param n: An integers.
        @return: An integer which is the first bad version.
        """
        def findFirstBadVersion(self, n):
            # write your code here
            if n == 1:
                return 1
            left = 1
            right = n
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if SVNRepo.isBadVersion(mid):
                    right = mid
                else:
                    left = mid
            if SVNRepo.isBadVersion(left):
                return left
            else:
                return right
    

    17.4.8二刷

    #class SVNRepo:
    #    @classmethod
    #    def isBadVersion(cls, id)
    #        # Run unit tests to check whether verison `id` is a bad version
    #        # return true if unit tests passed else false.
    # You can use SVNRepo.isBadVersion(10) to check whether version 10 is a 
    # bad version.
    class Solution:
        """
        @param n: An integers.
        @return: An integer which is the first bad version.
        """
        def findFirstBadVersion(self, n):
            # write your code here
            left, right = 1, n
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if SVNRepo.isBadVersion(mid):
                    right = mid
                else:
                    left = mid
                    
            if SVNRepo.isBadVersion(left):
                return left
            else:
                return right
    

      

    -------------------------------------------------------------------------

    62.搜索旋转排序数组

    假设有一个排序的按未知的旋转轴旋转的数组(比如,0 1 2 4 5 6 7 可能成为4 5 6 7 0 1 2)。给定一个目标值进行搜索,如果在数组中找到目标值返回数组中的索引位置,否则返回-1。你可以假设数组中不存在重复的元素。

    要点:多种情况的判断

    class Solution:
        """
        @param A : a list of integers
        @param target : an integer to be searched
        @return : an integer
        """
        def search(self, A, target):
            # write your code here
            if not A or target is None:
                return -1
            left = 0
            right = len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[right] < target:
                    if A[mid] < A[right]:
                        right = mid
                    elif A[mid] > target:
                        right = mid
                    else:
                        left = mid
                else:
                    if A[mid] < target:
                        left = mid
                    elif A[mid] > A[right]:
                        left = mid
                    else:
                        right = mid
            
            if A[left] == target:
                return left
            if A[right] == target:
                return right
            return -1
            
            
                    
    

    17.4.9二刷

    要注意target与left right相等的情况

    class Solution:
        """
        @param A : a list of integers
        @param target : an integer to be searched
        @return : an integer
        """
        def search(self, A, target):
            # write your code here
            if not A or target is None:
                return -1
                
            left, right = 0, len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[left] < A[right]:
                    if A[mid] >= target:
                        right = mid
                    else:
                        left = mid
                else:
                    if target >= A[left]:
                        if A[left] < A[mid] <= target:
                            left = mid
                        else:
                            right = mid
                    else:
                        if target <= A[mid] < A[right]:
                            right = mid
                        else:
                            left = mid
            if A[left] == target:
                return left
            if A[right] == target:
                return right
            return -1
    

      

    -------------------------------------------------------------------------

    600. Smallest Rectangle Enclosing Black Pixels

    寻找能套住图中黑色像素的最小矩形。

    要点:四次二分法,二刷要优化一下代码

    class Solution(object):
        # @param image {List[List[str]]}  a binary matrix with '0' and '1'
        # @param x, y {int} the location of one of the black pixels
        # @return an integer
        def minArea(self, image, x, y):
            # Write your code here
            m, n = len(image), len(image[0])
            left, right = 0, x
            while left + 1 < right:
                mid = (right - left) / 2 + left
                flag = False
                for i in range(n):
                    if image[mid][i] == '1':
                        flag = True
                        break
                if not flag:
                    left = mid
                else:
                    right = mid
            flag = False
            for i in range(n):
                if image[left][i] == '1':
                    flag = True
                    break
            if not flag:
                row1 = right
            else:
                row1 = left
                
            left, right = x, m - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                flag = False
                for i in range(n):
                    if image[mid][i] == '1':
                        flag = True
                        break
                if not flag:
                    right = mid
                else:
                    left = mid
            flag = False
            for i in range(n):
                if image[right][i] == '1':
                    flag = True
                    break
            if not flag:
                row2 = left
            else:
                row2 = right  
    
            left, right = 0, y
            while left + 1 < right:
                mid = (right - left) / 2 + left
                flag = False
                for i in range(m):
                    if image[i][mid] == '1':
                        flag = True
                        break
                
                if flag:
                    right = mid
                else:
                    left = mid
            flag = False
            for i in range(m):
                if image[i][left] == '1':
                    flag = True
                    break
            if not flag:
                col1 = right
            else:
                col1 = left
                
            left, right = y, n - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                flag = False
                for i in range(m):
                    if image[i][mid] == '1':
                        flag = True
                        break
                if flag:
                    left = mid
                else:
                    right = mid
            flag = False
            for i in range(m):
                if image[i][right] == '1':
                    flag = True
                    break
            if not flag:
                col2 = left
            else:
                col2 = right
            return (row2 + 1 - row1) * (col2 + 1 - col1)
            
    

    17.4.9二刷

    class Solution(object):
        # @param image {List[List[str]]}  a binary matrix with '0' and '1'
        # @param x, y {int} the location of one of the black pixels
        # @return an integer
        def minArea(self, image, x, y):
            # Write your code here
            m, n = len(image) - 1, len(image[0]) - 1
            row_left = self.binSearch(image, 0, x, 'row', True)
            row_right = self.binSearch(image, x, m, 'row', False)
            col_left = self.binSearch(image, 0, y, 'col', True)
            col_right = self.binSearch(image, y, n, 'col', False)
            return (row_right - row_left + 1) * (col_right - col_left + 1)
            
        def binSearch(self, image, left, right, type, isFindStart):
            while left + 1 < right:
                mid = (right - left) / 2 + left 
                if self.check(image, mid, type, isFindStart):
                    right = mid
                else:
                    left = mid
                    
            if self.check(image, left, type, isFindStart):
                return left if isFindStart else left - 1
            if self.check(image, right, type, isFindStart):
                return right if isFindStart else right - 1
            return len(image) - 1 if type == 'row' else len(image[0]) - 1
                
        def check(self, image, index, type, isFindStart):
            m, n = len(image), len(image[0])
            if type == 'row':
                for i in range(n):
                    if image[index][i] == '1':
                        return False ^ isFindStart
                return True ^ isFindStart
            else:
                for i in range(m):
                    if image[i][index] == '1':
                        return False ^ isFindStart
                return True ^ isFindStart
    

      

    -------------------------------------------------------------------------

    462.Total Occurrence of Target

    Given a target number and an integer array sorted in ascending order. Find the total number of occurrences of target in the array.

    class Solution:
        # @param {int[]} A an integer array sorted in ascending order
        # @param {int} target an integer
        # @return {int} an integer
        def totalOccurrence(self, A, target):
            # Write your code here
            if not A or not target:
                return 0
                
            left1 = 0
            right1 = len(A) - 1
            while left1 + 1 < right1:
                mid1 = (right1 - left1) / 2 + left1
                if A[mid1] >= target:
                    right1 = mid1
                else:
                    left1 = mid1
            
            startIndex = -1
            if A[left1] == target:
                startIndex = left1
            elif A[right1] == target:
                startIndex = right1
            if startIndex == -1:
                return 0
            
            left2 = 0
            right2 = len(A) - 1
            while left2 + 1 < right2:
                mid2 = (right2 - left2) / 2 + left2
                if A[mid2] <= target:
                    left2 = mid2
                else:
                    right2 = mid2
            
            endIndex = -1
            if A[right2] == target:
                endIndex = right2
            elif A[left2] == target:
                endIndex = left2
            if endIndex == -1:
                return 0
    
            return endIndex - startIndex + 1
            
    

    17.4.9二刷

    class Solution:
        # @param {int[]} A an integer array sorted in ascending order
        # @param {int} target an integer
        # @return {int} an integer
        def totalOccurrence(self, A, target):
            # Write your code here
            if not A or target is None:
                return 0
                
            left = self.binSearch(A, target, True)
            right = self.binSearch(A, target, False)
            
            if left == -1:
                return 0
            return right - left + 1
            
        def binSearch(self, A, target, isFirst):
            left, right = 0, len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if isFirst and A[mid] < target:
                    left = mid
                elif (not isFirst) and A[mid] <= target:
                    left = mid
                else:
                    right = mid
            if isFirst:
                if A[left] == target:
                    return left
                if A[right] == target:
                    return right
            else:
                if A[right] == target:
                    return right
                if A[left] == target:
                    return left
            return -1
    

    -------------------------------------------------------------------------

    254.Drop Eggs

    经典的丢鸡蛋问题

    class Solution:
        # @param {int} n an integer
        # @return {int} an integer
        def dropEggs(self, n):
            # Write your code here
            if not n:
                return 0
                
            left = 1
            right = n
            
            while left + 1 < right:
                mid = (right - left) / 2 + left
                temp = 0.5 * mid ** 2 + 0.5 * mid - n + 1
                if temp >= 0:
                    right = mid
                elif temp < 0:
                    left = mid
                    
            return left if (0.5 * left ** 2 + 0.5 * left - n + 1) > 0 else right
    

    17.4.9二刷

    class Solution:
        # @param {int} n an integer
        # @return {int} an integer
        def dropEggs(self, n):
            # Write your code here
            if not n:
                return 0
                
            left, right = 1, n
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if (1 + mid) * mid / 2 >= n:
                    right = mid
                else:
                    left = mid
                    
            if (1 + left) * left / 2 >= n:
                return left
            return right
    

      

    -------------------------------------------------------------------------

    14.First Position of Target

    find first X in OOXX

    class Solution:
        # @param nums: The integer array
        # @param target: Target number to find
        # @return the first position of target in nums, position start from 0
        def binarySearch(self, nums, target):
            # write your code here
            if not nums:
                return -1
            left = 0
            right = len(nums) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if nums[mid] >= target:
                    right = mid
                else:
                    left = mid
            if nums[left] == target:
                return left
            if nums[right] == target:
                return right
            return -1

    17.4.9二刷

    class Solution:
        # @param nums: The integer array
        # @param target: Target number to find
        # @return the first position of target in nums, position start from 0 
        def binarySearch(self, nums, target):
            # write your code here
            if not nums or target is None:
                return -1
                
            left, right = 0, len(nums) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if nums[mid] < target:
                    left = mid
                else:
                    right = mid
            for index in (left, right):        
                if nums[index] == target:
                    return index
            return -1
    

    -------------------------------------------------------------------------

    460.K Closest Numbers In Sorted Array

    find k closest numbers to target in A. A is in ascending order.

    class Solution:
        # @param {int[]} A an integer array
        # @param {int} target an integer
        # @param {int} k a non-negative integer
        # @return {int[]} an integer array
        def kClosestNumbers(self, A, target, k):
            # Write your code here
            result = []
            left = 0
            right = len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[mid] >= target:
                    right = mid
                else:
                    left = mid
            
            while len(result) < k:
                if left >= 0 and right <= len(A) - 1:
                    if abs(A[left] - target) <= abs(A[right] - target):
                        result.append(A[left])
                        left -= 1
                    else:
                        result.append(A[right])
                        right += 1
                elif left >= 0:
                    result.append(A[left])
                    left -= 1
                else:
                    result.append(A[right])
                    right += 1
            return result
    

    17.4.9二刷

    class Solution:
        # @param {int[]} A an integer array
        # @param {int} target an integer
        # @param {int} k a non-negative integer
        # @return {int[]} an integer array
        def kClosestNumbers(self, A, target, k):
            # Write your code here
            left, right = 0, len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[mid] < target:
                    left = mid
                else:
                    right = mid
                    
            result = []
            while len(result) < k:
                while len(result) < k and left >= 0 and right < len(A):
                    if abs(target - A[left]) <= abs(target - A[right]):
                        result.append(A[left])
                        left -= 1
                    else:
                        result.append(A[right])
                        right += 1
                while len(result) < k and left >= 0:
                    result.append(A[left])
                    left -= 1
                while len(result) < k and right >= 0:
                    result.append(A[right])
                    right += 1
            return result
    

    -------------------------------------------------------------------------

    414.Divide Two Integers

    Divide two integers without using multiplication, division and mod operator.

    class Solution(object):
        def divide(self, dividend, divisor):
            INT_MAX = 2147483647
            if divisor == 0:
                return INT_MAX
            neg = dividend > 0 and divisor < 0 or dividend < 0 and divisor > 0
            a, b = abs(dividend), abs(divisor)
            ans, shift = 0, 31
            while shift >= 0:
                if a >= b << shift:
                    a -= b << shift
                    ans += 1 << shift
                shift -= 1
            if neg:
                ans = - ans
            if ans > INT_MAX:
                return INT_MAX
            return ans
    

    -------------------------------------------------------------------------

    414.Divide Two Integers

    两数相除,不许用除号和取余,注意上下溢出。

    位运算 >>, <<

    17.4.10二刷

    class Solution:
        # @param {int} dividend the dividend
        # @param {int} divisor the divisor
        # @return {int} the result
        def divide(self, dividend, divisor):
            # Write your code here
            INT_MAX = 2147483647
            if divisor == 0:
                return INT_MAX if dividend >= 0 else -INT_MAX - 1
                
            neg = dividend >= 0 and divisor < 0 or dividend < 0 and divisor > 0
            
            dividend, divisor = abs(dividend), abs(divisor)
            ans, shift = 0, 31
            while shift >= 0:
                if dividend >= divisor << shift:
                    dividend -= divisor << shift
                    ans += 1 << shift
                shift -= 1
            if neg:
                ans = -ans
            if ans > INT_MAX:
                ans = INT_MAX
            if ans < -INT_MAX - 1:
                ans = -INT_MAX - 1
            
            return ans
    

      

    -------------------------------------------------------------------------

    61.search-for-a-range

    Given a sorted array of n integers, find the starting and ending position of a given target value.

    class Solution:
        """
        @param A : a list of integers
        @param target : an integer to be searched
        @return : a list of length 2, [index1, index2]
        """
        def searchRange(self, A, target):
            # write your code here
            if not A or target is None:
                return [-1, -1]
            left = 0
            right = len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[mid] >= target:
                    right = mid
                else:
                    left = mid
            if A[left] == target:
                leftBound = left
            elif A[right] == target:
                leftBound = right
            else:
                return [-1, -1]
                
            left = 0
            right = len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[mid] > target:
                    right = mid
                else:
                    left = mid
            if A[right] == target:
                rightBound = right
            elif A[left] == target:
                rightBound = left
            
            return [leftBound, rightBound]
            
            
    

    17.4.9二刷

    class Solution:
        """
        @param A : a list of integers
        @param target : an integer to be searched
        @return : a list of length 2, [index1, index2]
        """
        def searchRange(self, A, target):
            # write your code here
            if not A or target is None:
                return [-1, -1]
            
            return [self.binSearch(A, target, True), 
                    self.binSearch(A, target, False)]
            
        def binSearch(self, A, target, isFirst):
            left, right = 0, len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if isFirst and A[mid] < target:
                    left = mid
                elif (not isFirst) and A[mid] <= target:
                    left = mid
                else:
                    right = mid
            if isFirst:
                if A[left] == target:
                    return left
                if A[right] == target:
                    return right
            else:
                if A[right] == target:
                    return right
                if A[left] == target:
                    return left
            return -1
    

    -------------------------------------------------------------------------

    38.Search a 2D Matrix II

    Search for a value in an m x n matrix, return the occurrence of it.

    This matrix has the following properties:

    • Integers in each row are sorted from left to right.
    • Integers in each column are sorted from up to bottom.
    • No duplicate integers in each row or column.
    class Solution:
        """
        @param matrix: An list of lists of integers
        @param target: An integer you want to search in matrix
        @return: An integer indicates the total occurrence of target in the given matrix
        """
        def searchMatrix(self, matrix, target):
            # write your code here
            result = 0
            if not matrix or target is None:
                return result
            row = len(matrix) - 1
            col = 0
            while col <= len(matrix[0]) - 1 and row >= 0:
                if matrix[row][col] < target:
                    col += 1
                elif matrix[row][col] > target:
                    row -= 1
                else:
                    result += 1
                    col += 1
                    row -= 1
            return result
    

    17.4.10二刷:

    主对角线方向入手的,加入二分

    class Solution:
        """
        @param matrix: An list of lists of integers
        @param target: An integer you want to search in matrix
        @return: An integer indicates the total occurrence of target in the given matrix
        """
        def searchMatrix(self, matrix, target):
            # write your code here
            if not matrix or not matrix[0]:
                return 0
            m, n, result = len(matrix), len(matrix[0]), 0
            row, col = 0, 0
            while row < m and col < n and matrix[row][col] <= target:
                if matrix[row][col] == target:
                    result += 1
                else:
                    if self.binSearch(matrix, row, col, 'row', target) != -1:
                        result += 1
                    if self.binSearch(matrix, col, row, 'col', target) != -1:
                        result += 1
                row += 1
                col += 1
                
            return result
            
        def binSearch(self, matrix, index, start, type, target):
            left, right = start, len(matrix[0]) - 1 if type == 'row' else len(matrix) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if type == 'row' and matrix[index][mid] < target:
                    left = mid
                elif type == 'col' and matrix[mid][index] < target:
                    left = mid
                else:
                    right = mid
            if type == 'row':
                if matrix[index][left] == target:
                    return left
                elif matrix[index][right] == target:
                    return right
                return -1
            else:
                if matrix[left][index] == target:
                    return left
                elif matrix[right][index] == target:
                    return right
                return -1
                
            
    

    -------------------------------------------------------------------------  

    457.Classical Binary Search

    17.4.10二刷

    class Solution:
        # @param {int[]} A an integer array sorted in ascending order
        # @param {int} target an integer
        # @return {int} an integer
        def findPosition(self, A, target):
            # Write your code here
            if not A or target is None:
                return -1
                
            left, right = 0, len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[mid] < target:
                    left = mid
                elif A[mid] == target:
                    return mid
                else:
                    right = mid
                    
            if A[left] == target:
                return left
            if A[right] == target:
                return right
            return -1
    

    -------------------------------------------------------------------------

    141.Sqrt(x)

    Compute and return the square root of x. return int.

    class Solution:
        """
        @param x: An integer
        @return: The sqrt of x
        """
        def sqrt(self, x):
            # write your code here
            if not x:
                return 0
            left = 1
            right = x
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if mid ** 2 <= x:
                    left = mid
                else:
                    right = mid
            if right ** 2 <= x:
                return right
            if left ** 2 <= x:
                return left
            return 0
                    
            
    

    17.4.10二刷

    class Solution:
        """
        @param x: An integer
        @return: The sqrt of x
        """
        def sqrt(self, x):
            # write your code here
            left, right = 0, x
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if mid ** 2 >= x:
                    right = mid
                else:
                    left = mid
            if left ** 2 >= x:
                return left if left ** 2 == x else left - 1
            return right if right ** 2 == x else right - 1
    

    -------------------------------------------------------------------------

    617.Maximum Average Subarray

    寻找平均值最大的,长度大于等于k的子数组

    首先利用二分思想找到潜在的最大值。

    在计算前缀和的平均值时,有个巧妙的变化:每一项都减去mid,如果存在一个子数组(长度大于k)的和>0,就是说明存在一个子数组的和大于mid。这样就变成了传统的最大子数组问题。

    class Solution:
        # @param {int[]} nums an array with positive and negative numbers
        # @param {int} k an integer
        # @return {double} the maximum average
        def maxAverage(self, nums, k):
            # Write your code here
            left, right = min(nums), max(nums)
            prefix = [0] * (len(nums) + 1)
            while right - left >= 1e-6:
                mid, check = (right + left) / 2.0, False
                min_pre = 0
                for i in xrange(1, len(nums) + 1):
                    prefix[i] = prefix[i - 1] + nums[i - 1] - mid
                    if i >= k and prefix[i] >= min_pre:
                        check = True
                        break
                    if i >= k:
                        min_pre = min(min_pre, prefix[i - k + 1])
                if check:
                    left = mid
                else:
                    right = mid
            return left
    

    17.4.20二刷:

    class Solution:
        # @param {int[]} nums an array with positive and negative numbers
        # @param {int} k an integer
        # @return {double} the maximum average
        def maxAverage(self, nums, k):
            # Write your code here
            left, right = min(nums), max(nums)
            prefix = [0] * (len(nums) + 1)
            while right - left > 1e-6:
                mid = (left + right) / 2.0
                min_pre = 0
                check = False
                for i in xrange(1, len(nums) + 1):
                    prefix[i] = prefix[i - 1] + nums[i - 1] - mid
                    if i >= k and prefix[i] > min_pre:
                        check = True
                        break
                    if i >= k:
                        min_pre = min(min_pre, prefix[i - k + 1])
                if check:
                    left = mid
                else:
                    right = mid
                    
            return right

    -------------------------------------------------------------------------

    586.Sqrt(x) II

    注意小于1的时候,不需要double check

    17.4.10

    class Solution:
        # @param {double} x a double
        # @return {double} the square root of x
        def sqrt(self, x):
            # Write your code here
            if not x:
                return 0
            # binary on result
            left = 0.0
            right = x if x > 1 else 1
            while left + 1e-12< right:
                mid = (right - left) / 2.0 + left
                midSquare = mid ** 2
                if midSquare < x:
                    left = mid
                else:
                    right = mid
            # or u can return right
            return right
    

    -------------------------------------------------------------------------

    160.Find Minimum in Rotated Sorted Array II

    Suppose a sorted array is rotated at some pivot unknown to you beforehand.

    The array may contain duplicates.

    class Solution:
        # @param num: a rotated sorted array
        # @return: the minimum number in the array
        def findMin(self, nums):
            # write your code here
            if not nums:
                return -1
                
            left = 0
            right = len(nums) - 1
            
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if nums[mid] < nums[right]:
                    right = mid
                elif nums[mid] > nums[right]:
                    left = mid
                else:
                    if self.judge(nums, mid, right):
                        right = mid
                    else:
                        left = mid
            return nums[left] if nums[left] < nums[right] else nums[right]
            
        def judge(self, A, mid, right):
            temp = None
            for i in A[mid:right + 1]:
                if temp is None or i == temp:
                    temp = i
                else:
                    return False
            return True
    

      

    17.4.10二刷

    class Solution:
        # @param num: a rotated sorted array
        # @return: the minimum number in the array
        def findMin(self, num):
            # write your code here
            left, right = 0, len(num) - 1
            while left + 1 < right:
                if num[left] < num[right]:
                    return num[left]
                mid = (right - left) / 2 + left
                if num[mid] > num[left]:
                    left = mid
                elif num[mid] < num[right]:
                    right = mid
                elif num[mid] == num[right] and num[mid] < num[left]:
                    right = mid
                elif num[mid] == num[left] and num[mid] > num[right]:
                    left = mid
                else:
                    flag = False
                    for i in xrange(left, mid + 1):
                        if num[i] != num[left]:
                            flag = True
                            break
                    if not flag:
                        left = mid
                    else:
                        right = mid
                        
            return num[left] if num[left] < num[right] else num[right]       
    

    -------------------------------------------------------------------------

    63.Search in Rotated Sorted Array II

    Follow up for Search in Rotated Sorted Array:What if duplicates are allowed?

    class Solution:
        """
        @param A : an integer ratated sorted array and duplicates are allowed
        @param target : an integer to be searched
        @return : a boolean
        """
        def search(self, A, target):
            # write your code here
            if not A or target is None:
                return False
            left = 0
            right = len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[right] < target:
                    if A[mid] < A[right]:
                        right = mid
                    elif A[mid] == A[right]:
                        if self.judge(A, left, mid, right):
                            left = mid
                        else:
                            right = mid
                    elif A[mid] > target:
                        right = mid
                    else:
                        left = mid
                else:
                    if A[mid] < target:
                        left = mid
                    elif A[mid] > A[right]:
                        left = mid
                    elif A[mid] == A[right]:
                        if self.judge(A, left, mid, right):
                            left = mid
                        else:
                            right = mid
                    else:
                        right = mid
            
            if A[left] == target:
                return True
            if A[right] == target:
                return True
            return False
            
        def judge(self, A, left, mid, right):
            temp = None
            for i in A[left:mid + 1]:
                if temp is None or i == temp:
                    temp = i
                else:
                    return False
            return True
            
    

    17.4.10二刷

    class Solution:
        """
        @param A : an integer ratated sorted array and duplicates are allowed
        @param target : an integer to be searched
        @return : a boolean
        """
        def search(self, A, target):
            # write your code here
            if not A or target is None:
                return False
                
            left, right = 0, len(A) - 1
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if A[left] < A[right]:
                    if target > A[mid]:
                        left = mid
                    elif target < A[mid]:
                        right = mid
                    else:
                        return True
                else:
                    if target < A[right]:
                        if A[mid] < target or A[mid] > A[left]:
                            left = mid
                        elif A[mid] > target:
                            right = target
                        else:
                            return True
                    elif target > A[left]:
                        if A[mid] < A[right] or A[mid] > target:
                            right = mid
                        elif A[mid] < target:
                            left = mid
                        else:
                            return True
                    else:
                        return True
                        
            if A[left] == target or A[right] == target:
                return True
            return False
    

    -------------------------------------------------------------------------

    437.Copy Books

    二分答案

    class Solution:
        # @param pages: a list of integers
        # @param k: an integer
        # @return: an integer
        def copyBooks(self, pages, k):
            # write your code here
            if not pages or not k:
                return 0
                
            left = max(pages)
            right = sum(pages)
            
            while left + 1 < right:
                mid = (right - left) / 2 + left
                staffCount = self.copyHelper(pages, mid)
                if staffCount <= k:
                    right = mid
                else:
                    left = mid
            
            if self.copyHelper(pages, left) <= k:
                return left
            else:
                return right
                
        def copyHelper(self, pages, maxWork):
            result = 0
            temp = 0
            for page in pages:
                if temp + page <= maxWork:
                    temp += page
                else:
                    temp = page
                    result += 1
            result += 1
            return result
    

    17.4.10二刷:

    class Solution:
        # @param pages: a list of integers
        # @param k: an integer
        # @return: an integer
        def copyBooks(self, pages, k):
            # write your code here
            left, right = 0, sum(pages)
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if self.check(pages, k, mid):
                    right = mid
                else:
                    left = mid
                    
            if self.check(pages, k, left):
                return left
            return right
            
        def check(self, pages, k, cost):
            person = 1
            work = 0
            for p in pages:
                if p > cost:
                    return False
                if work + p <= cost:
                    work += p
                else:
                    person += 1
                    work = p
            return person <= k
    

    -------------------------------------------------------------------------

    183.Wood Cut

    把这些木头切割成一些长度相同的小段木头,小段的数目至少为 k,小段越长越好。

    class Solution:
        """
        @param L: Given n pieces of wood with length L[i]
        @param k: An integer
        return: The maximum length of the small pieces.
        """
        def woodCut(self, L, k):
            # write your code here
            if not L or not k:
                return 0
                
            left = 1
            right = max(L)
            
            while left + 1 < right:
                mid = (right - left) / 2 + left
                maxNum = self.checkWood(L, mid)
                if maxNum >= k:
                    left = mid
                else:
                    right = mid
            
            if self.checkWood(L, right) >= k:
                return right
            if self.checkWood(L, left) >= k:
                return left
            return 0
            
        def checkWood(self, L, length):
            result = 0
            for wood in L:
                result += wood / length
            return result
    

    17.4.10二刷

    class Solution:
        """
        @param L: Given n pieces of wood with length L[i]
        @param k: An integer
        return: The maximum length of the small pieces.
        """
        def woodCut(self, L, k):
            # write your code here
            if not L:
                return 0
            left, right = 0, max(L)
            while left + 1 < right:
                mid = (right - left) / 2 + left
                if self.check(L, k, mid):
                    left = mid
                else:
                    right = mid
            if self.check(L, k, right):
                return right
            return left
            
        def check(self, L, k, length):
            result = 0
            for l in L:
                result += l / length
            return result >= k
    

      

    3 - 二叉树与分治法


    597.Subtree with Maximum Average

    求最大的子树平均值

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            this.val = val
            this.left, this.right = None, None
    """
    
    
    class Solution:
        # @param {TreeNode} root the root of binary tree
        # @return {TreeNode} the root of the maximum average of subtree
        def findSubtree2(self, root):
            # Write your code here
            self.maxAvgNode = None
            self.maxAvg = None
            self.dcFind(root)
            return self.maxAvgNode
            
        def dcFind(self, root):
            if not root:
                return {'size': 0, 'sum': 0}
            
            leftSub = self.dcFind(root.left)
            rightSub = self.dcFind(root.right)
            
            result = {
                        'size': leftSub['size'] + rightSub['size'] + 1,
                        'sum': leftSub['sum'] + rightSub['sum'] + root.val
                      }
            if not self.maxAvgNode or self.maxAvg['sum'] * result['size'] 
                < result['sum'] * self.maxAvg['size']:
                self.maxAvgNode = root
                self.maxAvg = result
            return result
    

    17.4.20二刷:

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            this.val = val
            this.left, this.right = None, None
    """
    import sys
    class Solution:
        # @param {TreeNode} root the root of binary tree
        # @return {TreeNode} the root of the maximum average of subtree
        def findSubtree2(self, root):
            # Write your code here
            self.max_average = -sys.maxint
            self.result_node = None
            self.helper(root)
            return self.result_node
            
        def helper(self, root):
            if not root:
                return 0, 0
            left_sum, left_count = self.helper(root.left)
            right_sum, right_count = self.helper(root.right)
            if (left_sum + right_sum + root.val) / float(left_count + right_count + 1) > self.max_average:
                self.max_average = (left_sum + right_sum + root.val) / float(left_count + right_count + 1)
                self.result_node = root
            return (left_sum + right_sum + root.val), (left_count + right_count + 1)
    

    -------------------------------------------------------------------------

    93.Balanced Binary Tree

    检查一棵树是不是平衡的

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    
    
    class Solution:
        """
        @param root: The root of binary tree.
        @return: True if this Binary tree is Balanced, or false.
        """
        def isBalanced(self, root):
            # write your code here
            return self.traversalHelper(root)[1]
        
        def traversalHelper(self, root):
            if not root:
                return 0, True
            ldepth, lresult = self.traversalHelper(root.left)
            if lresult:
                rdepth, rresult = self.traversalHelper(root.right)
                if rresult:
                    return max(ldepth, rdepth) + 1, abs(ldepth - rdepth) <= 1
                else:
                    return max(ldepth, rdepth) + 1, False
            else:
                return ldepth + 1, False
    

    17.4.20二刷:

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    class Solution:
        """
        @param root: The root of binary tree.
        @return: True if this Binary tree is Balanced, or false.
        """
        def isBalanced(self, root):
            # write your code here
            return False if self.helper(root) == -1 else True
            
            
        def helper(self, root):
            if not root:
                return 0
            left = self.helper(root.left)
            right = self.helper(root.right)
            
            if left == -1 or right == -1:
                return -1
                
            if abs(left - right) > 1:
                return -1
                
            return max(left, right) + 1
    

    -------------------------------------------------------------------------

    97.Maximum Depth of Binary Tree

    返回一个二叉树的最大深度

    class Solution:
        """
        @param root: The root of binary tree.
        @return: An integer
        """
        def maxDepth(self, root):
            # write your code here
            return self.traversalHelper(root, 0)
    
        def traversalHelper(self, root, depth):
            if not root:
                return depth
            return max(
                        self.traversalHelper(root.left, depth + 1),
                        self.traversalHelper(root.right, depth + 1)
                        )
    

    17.4.20二刷:

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    class Solution:
        """
        @param root: The root of binary tree.
        @return: An integer
        """ 
        def maxDepth(self, root):
            # write your code here
            if not root:
                return 0
                
            return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
    

    -------------------------------------------------------------------------

    480.Binary Tree Paths

    找到二叉树到叶子节点所有路径

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    class Solution:
        # @param {TreeNode} root the root of the binary tree
        # @return {List[str]} all root-to-leaf paths
        def binaryTreePaths(self, root):
            # Write your code here
            result = []
            self.traversalHelper(root, result, [])
            return result
        
        def traversalHelper(self, root, result, path):
            if not root:
                return
            path.append(str(root.val))
            if not root.left and not root.right:
                result.append('->'.join(path))
                return
            self.traversalHelper(root.left, result, path[:])
            self.traversalHelper(root.right, result, path[:])
    

    17.4.20二刷

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    class Solution:
        # @param {TreeNode} root the root of the binary tree
        # @return {List[str]} all root-to-leaf paths
        def binaryTreePaths(self, root):
            # Write your code here
            result = self.helper(root)
            for i in xrange(len(result)):
                result[i] = '->'.join(result[i][::-1])
            return result
            
        def helper(self, root):
            if not root:
                return []
            if (not root.left) and (not root.right):
                return [[str(root.val)]]
                
            child = self.helper(root.left)
            child.extend(self.helper(root.right))
            
            for li in child:
                li.append(str(root.val))
            return child
    

    -------------------------------------------------------------------------

    376.Binary Tree Path Sum

    找到二叉树到叶子节点所有路径,和为target的

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    class Solution:
        # @param {TreeNode} root the root of binary tree
        # @param {int} target an integer
        # @return {int[][]} all valid paths
        def binaryTreePathSum(self, root, target):
            # Write your code here
            result = []
            self.traverseHelper(root, [], target, result)
            return result
            
        def traverseHelper(self, root, path, target, result):
            if not root:
                return
            path.append(root.val)
            if root.left is None and root.right is None:
                if sum(path) == target:
                    result.append(path)
            else:
                self.traverseHelper(root.left, path[:], target, result)
                self.traverseHelper(root.right, path[:], target, result)
    

    17.4.20二刷:

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    class Solution:
        # @param {TreeNode} root the root of binary tree
        # @param {int} target an integer
        # @return {int[][]} all valid paths
        def binaryTreePathSum(self, root, target):
            # Write your code here
            temp = self.helper(root)
            result = []
            for i in xrange(len(temp)):
                if sum(temp[i]) == target:
                    result.append(temp[i])
            return result
            
        def helper(self, root):
            if not root:
                return []
            if (not root.left) and (not root.right):
                return [[root.val]]
                
            child = self.helper(root.left)
            child.extend(self.helper(root.right))
            
            for li in child:
                li.insert(0, root.val)
            return child
    

    -------------------------------------------------------------------------

    596.Minimum Subtree

    找到二叉树中的最小子树

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            this.val = val
            this.left, this.right = None, None
    """
    class Solution:
        # @param {TreeNode} root the root of binary tree
        # @return {TreeNode} the root of the minimum subtree
        def findSubtree(self, root):
            # Write your code here
            self.minSum = None
            self.minSumNode = None
            self.dcFind(root)
            return self.minSumNode
        
        def dcFind(self, root):
            if not root:
                return 0
            
            result = self.dcFind(root.left) + self.dcFind(root.right) + root.val
            
            if not self.minSumNode or self.minSum > result:
                self.minSum = result
                self.minSumNode = root
            
            return result
    

    17.4.20二刷:

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            this.val = val
            this.left, this.right = None, None
    """
    class Solution:
        # @param {TreeNode} root the root of binary tree
        # @return {TreeNode} the root of the minimum subtree
        def findSubtree(self, root):
            # Write your code here
            self.min_sum = sys.maxint
            self.result_node = None
            self.helper(root)
            return self.result_node
            
        def helper(self, root):
            if not root:
                return 0
            left_sum = self.helper(root.left)
            right_sum = self.helper(root.right)
            if left_sum + right_sum + root.val < self.min_sum:
                self.min_sum = left_sum + right_sum + root.val
                self.result_node = root
            return left_sum + right_sum + root.val
    

    -------------------------------------------------------------------------

    595.Binary Tree Longest Consecutive Sequence

    寻找二叉树中从上至下方向中的最长的连续序列,返回长度

    # Definition for a binary tree node.
    # class TreeNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        # @param {TreeNode} root the root of binary tree
        # @return {int} the length of the longest consecutive sequence path
        def longestConsecutive(self, root):
            # Write your code here
            self.maxLength = 0
            self.dcFind(root)
            return self.maxLength
            
        def dcFind(self, root):
            if not root:
                return {
                            'len': 0,
                            'val': -1
                        }
            
            left = self.dcFind(root.left)
            right = self.dcFind(root.right)
            
            result = {'len': 1,'val':root.val}
            if left['val'] == root.val + 1:
                result['len'] = left['len'] + 1
            if right['val'] == root.val + 1 and result['len'] < right['len'] + 1:
                result['len'] = right['len'] + 1
            if result['len'] > self.maxLength:
                self.maxLength = result['len']
            return result
    

    17.4.20二刷

    # Definition for a binary tree node.
    # class TreeNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        # @param {TreeNode} root the root of binary tree
        # @return {int} the length of the longest consecutive sequence path
        def longestConsecutive(self, root):
            # Write your code here
            self.max_len = 0
            self.helper(root)
            return self.max_len
            
        def helper(self, root):
            if not root:
                return 0
            left, right, result = 0, 0, 1
            if root.left:
                left = self.helper(root.left)
                if root.val + 1 == root.left.val:
                    result += left
            if root.right:
                right = self.helper(root.right)
                if root.val + 1 == root.right.val:
                    result = max(right + 1, result)
            self.max_len = max(self.max_len, left, right, result)
            return result
    

    -------------------------------------------------------------------------

    453.Flatten Binary Tree to Linked List

    将一个二叉树转换为链表

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            this.val = val
            this.left, this.right = None, None
    """
    
    
    class Solution:
        # @param root: a TreeNode, the root of the binary tree
        # @return: nothing
        def flatten(self, root):
            # write your code here
            if not root:
                return
            self.traversalHelper(root)
    
        def traversalHelper(self, root):
            if root.right:
                self.traversalHelper(root.right)
            if root.left:
                self.traversalHelper(root.left)
                leftStart = root.left
                leftEnd = root.left
                while leftEnd.right:
                    leftEnd = leftEnd.right
                root.left = None
                rightStart = root.right
                root.right = leftStart
                leftEnd.right = rightStart
    

    17.4.20二刷:

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            this.val = val
            this.left, this.right = None, None
    """
    class Solution:
        # @param root: a TreeNode, the root of the binary tree
        # @return: nothing
        def flatten(self, root):
            # write your code here
            if not root:
                return
            self.flatten(root.left)
            self.flatten(root.right)
            temp = root.right
            root.right = root.left
            root.left = None
            cur = root
            while cur.right:
                cur = cur.right
            cur.right = temp
    

    -------------------------------------------------------------------------

     578.Lowest Common Ancestor III

    找两个节点的最低公共祖先

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            this.val = val
            this.left, this.right = None, None
    """
    
    
    class Solution:
        """
        @param {TreeNode} root The root of the binary tree.
        @param {TreeNode} A and {TreeNode} B two nodes
        @return Return the LCA of the two nodes.
        """
        def lowestCommonAncestor3(self, root, A, B):
            # write your code here
            result = self.dcHelper(root, A, B)
            return result['result']
    
        def dcHelper(self, root, A, B):
            if not root:
                return {
                            'foundA': False,
                            'foundB': False,
                            'result': None
                        }
            else:
                left = self.dcHelper(root.left, A, B)
                right = self.dcHelper(root.right, A, B)
                result = {
                                'foundA': left['foundA'] or right['foundA'],
                                'foundB': left['foundB'] or right['foundB'],
                                'result': left['result'] if left['result'] else right['result']
                          }
                if root == A:
                    result['foundA'] = True
                if root == B:
                    result['foundB'] = True
                if result['result'] is None and result['foundA'] and result['foundB']:
                    result['result'] = root
                return result
    

    17.4.21二刷:

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            this.val = val
            this.left, this.right = None, None
    """
    class Solution:
        """
        @param {TreeNode} root The root of the binary tree.
        @param {TreeNode} A and {TreeNode} B two nodes
        @return Return the LCA of the two nodes.
        """ 
        def lowestCommonAncestor3(self, root, A, B):
            # write your code here
            pathA = self.get_path(root, A, [root])
            pathB = self.get_path(root, B, [root])
            if not pathA or not pathB:
                return 
            for i in range(min(len(pathA), len(pathB))):
                if pathA[i] != pathB[i]:
                    return pathA[i - 1]
            return pathA[-1] if len(pathA) < len(pathB) else pathB[-1]
            
        def get_path(self, root, target, path):
            if not root:
                return []
            if root == target:
                return path
            for node in (root.left, root.right):
                path.append(node)
                result = self.get_path(node, target, path)
                if result:
                    return result
                path.pop()
    

    -------------------------------------------------------------------------

    95.Validate Binary Search Tree

    验证是不是二叉查找树,左子树严格小于根,右子树严格大于根

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    class Solution:
        """
        @param root: The root of binary tree.
        @return: True if the binary tree is BST, or false
        """  
        def isValidBST(self, root):
            result = self.dcHelper(root)
            return result['result']
            
        def dcHelper(self, root):
            if not root:
                return {'result': True, 'min': None, 'max': None}
            else:
                left = self.dcHelper(root.left)
                right = self.dcHelper(root.right)
                if not left['result'] or not right['result']:
                    return {'result': False, 'min': None, 'max': None}
                elif (left['max'] and left['max'] >= root.val) 
                    or (right['min'] and right['min'] <= root.val):
                    return {'result': False, 'min': None, 'max': None}
                else:
                    return {
                                'result': True, 
                                'min': left['min'] if left['min'] else root.val, 
                                'max': right['max'] if right['max'] else root.val
                            }
    

    17.4.21二刷:

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    import sys
    class Solution:
        """
        @param root: The root of binary tree.
        @return: True if the binary tree is BST, or false
        """  
        def isValidBST(self, root):
            # write your code here
            self.result = True
            self.testBST(root)
            return self.result
            
        def testBST(self, root):
            if not root:
                return sys.maxint, -sys.maxint
            lsmall, lbig = self.testBST(root.left)
            rsmall, rbig = self.testBST(root.right)
            if lbig >= root.val or rsmall <= root.val:
                self.result = False
            return min(lsmall, root.val), max(rbig, root.val)
    

    -------------------------------------------------------------------------

    474.Lowest Common Ancestor II

    最小公共祖先,有指向父节点的指针

    """
    Definition of ParentTreeNode:
    class ParentTreeNode:
        def __init__(self, val):
            self.val = val
            self.parent, self.left, self.right = None, None, None
    """
    class Solution:
        """
        @param root: The root of the tree
        @param A and B: Two node in the tree
        @return: The lowest common ancestor of A and B
        """ 
        def lowestCommonAncestorII(self, root, A, B):
            # Write your code here
            parentA = []
            while A:
                parentA.append(A)
                A = A.parent
            while B:
                if B in parentA:
                    return B
                B = B.parent
    

    17.4.21二刷:

    """
    Definition of ParentTreeNode:
    class ParentTreeNode:
        def __init__(self, val):
            self.val = val
            self.parent, self.left, self.right = None, None, None
    """
    class Solution:
        """
        @param root: The root of the tree
        @param A and B: Two node in the tree
        @return: The lowest common ancestor of A and B
        """ 
        def lowestCommonAncestorII(self, root, A, B):
            # Write your code here
            pA = self.get_parent_list(A)
            pB = self.get_parent_list(B)
            if not pA or not pB:
                return
            for i in range(min(len(pA), len(pB))):
                if pA[i] != pB[i]:
                    return pA[i - 1]
            return pA[-1] if len(pA) < len(pB) else pB[-1]
            
        def get_parent_list(self, node):
            result = []
            cur = node
            while cur:
                result.append(cur)
                cur = cur.parent
            return result[::-1]
    

    -------------------------------------------------------------------------

    246.Binary Tree Path Sum II

    任意位置开始和结束,只能从上往下

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    class Solution:
        # @param {TreeNode} root the root of binary tree
        # @param {int} target an integer
        # @return {int[][]} all valid paths
        def binaryTreePathSum2(self, root, target):
            # Write your code here
            self.result = []
            if target is None:
                return self.result
            self.dcHelper(root, target)
            return self.result
            
        def dcHelper(self, root, target):
            dcResult = []
            if not root:
                return dcResult
            temp = self.dcHelper(root.left, target)
            temp.extend(self.dcHelper(root.right, target))
            #dcResult.extend(temp)
            temp.append([])
            for path in temp:
                path.insert(0, root.val)
                if sum(path) == target:
                    self.result.append(path[:])
                dcResult.append(path[:])
            return dcResult

    17.4.21二刷:

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    class Solution:
        # @param {TreeNode} root the root of binary tree
        # @param {int} target an integer
        # @return {int[][]} all valid paths
        def binaryTreePathSum2(self, root, target):
            # Write your code here
            self.result = []
            paths = self.helper(root, target)
            return self.result
            
        def helper(self, root, target):
            if not root:
                return []
            result = self.helper(root.left, target)
            result.extend(self.helper(root.right, target))
            for i in xrange(len(result)):
                result[i].append(root.val)
            result.append([root.val])
            for i in xrange(len(result)):
                if result[i] and sum(result[i]) == target:
                    self.result.append(result[i][::-1])
            return result
    

    -------------------------------------------------------------------------

    68.Binary Tree Postorder Traversal

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    
    
    class Solution:
        """
        @param root: The root of binary tree.
        @return: Postorder in ArrayList which contains node values.
        """
        def postorderTraversal(self, root):
            # write your code here
            result = []
            if not root:
                return result
            now = root
            markNode = None
            stack = []
            while stack or now:
                while now:
                    stack.append(now)
                    now = now.left
                now = stack.pop()
                if not now.right or now.right is markNode:
                    result.append(now.val)
                    markNode = now
                    now = None
                else:
                    stack.append(now)
                    now = now.right
            return result
    

    17.4.21二刷,递归版本,要背过非递归的

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    
    
    class Solution:
        """
        @param root: The root of binary tree.
        @return: Postorder in ArrayList which contains node values.
        """
        def postorderTraversal(self, root):
            # write your code here
            self.result = []
            self.helper(root)
            return self.result
            
        def helper(self, root):
            if not root:
                return
            self.helper(root.left)
            self.helper(root.right)
            self.result.append(root.val)
    

    -------------------------------------------------------------------------

    67.Binary Tree Inorder Traversal

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    
    
    class Solution:
        """
        @param root: The root of binary tree.
        @return: Inorder in ArrayList which contains node values.
        """
        def inorderTraversal(self, root):
            # write your code here
            result = []
            if root is None:
                return result
            stack = []
            now = root
            while now or stack:
                while now:
                    stack.append(now)
                    now = now.left
                now = stack.pop()
                result.append(now.val)
                now = now.right
            return result
    

    17.4.21二刷:

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    
    
    class Solution:
        """
        @param root: The root of binary tree.
        @return: Inorder in ArrayList which contains node values.
        """
        def inorderTraversal(self, root):
            # write your code here
            self.result = []
            self.helper(root)
            return self.result
            
        def helper(self, root):
            if not root:
                return
            self.helper(root.left)
            self.result.append(root.val)
            self.helper(root.right)
    

    -------------------------------------------------------------------------

    66.Binary Tree Preorder Traversal

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    
    
    class Solution:
        """
        @param root: The root of binary tree.
        @return: Preorder in ArrayList which contains node values.
        """
        def preorderTraversal(self, root):
            # write your code here
            result = []
            self.traversalHelper(root, result)
            return result
    
        def traversalHelper(self, root, result):
            if not root:
                return
            result.append(root.val)
            self.traversalHelper(root.left, result)
            self.traversalHelper(root.right, result)

    17.4.21二刷:

    """
    Definition of TreeNode:
    class TreeNode:
        def __init__(self, val):
            self.val = val
            self.left, self.right = None, None
    """
    
    
    class Solution:
        """
        @param root: The root of binary tree.
        @return: Preorder in ArrayList which contains node values.
        """
        def preorderTraversal(self, root):
            # write your code here
            self.result = []
            self.helper(root)
            return self.result
            
        def helper(self, root):
            if not root:
                return
            self.result.append(root.val)
            self.helper(root.left)
            self.helper(root.right)
    

    -------------------------------------------------------------------------

    4 - 宽度优先搜索

    7.binary-tree-serialization

    设计一个算法,并编写代码来序列化和反序列化二叉树。

     1 """
     2 Definition of TreeNode:
     3 class TreeNode:
     4     def __init__(self, val):
     5         self.val = val
     6         self.left, self.right = None, None
     7 """
     8 class Solution:
     9 
    10     '''
    11     @param root: An object of TreeNode, denote the root of the binary tree.
    12     This method will be invoked first, you should design your own algorithm 
    13     to serialize a binary tree which denote by a root node to a string which
    14     can be easily deserialized by your own "deserialize" method later.
    15     '''
    16     def serialize(self, root):
    17         # write your code here
    18         result = []
    19         if not root:
    20             return ','.join(result)
    21             
    22         queue = [root]
    23         while queue:
    24             node = queue.pop(0)
    25             result.append(str(node.val) if node else '#')
    26             if node:
    27                 queue.append(node.left)
    28                 queue.append(node.right)
    29         return ','.join(result)
    30         
    31     '''
    32     @param data: A string serialized by your serialize method.
    33     This method will be invoked second, the argument data is what exactly
    34     you serialized at method "serialize", that means the data is not given by
    35     system, it's given by your own serialize method. So the format of data is
    36     designed by yourself, and deserialize it here as you serialize it in 
    37     "serialize" method.
    38     '''
    39     def deserialize(self, data):
    40         # write your code here
    41         root = None
    42         if not data:
    43             return root
    44         data = data.split(',')
    45         
    46         root = TreeNode(int(data[0]))
    47         queue = [root]
    48         isLeftChild = True
    49         index = 0
    50         
    51         for val in data[1:]:
    52             if val is not '#':
    53                 node = TreeNode(int(val))
    54                 if isLeftChild:
    55                     queue[index].left = node
    56                 else:
    57                     queue[index].right = node
    58                 queue.append(node)
    59 
    60             if not isLeftChild:
    61                 index += 1
    62             isLeftChild = not isLeftChild
    63 
    64         return root
    65                 
    View Code

    17.5.29二刷

    序列化时加入父节点信息和左右信息

     1 """
     2 Definition of TreeNode:
     3 class TreeNode:
     4     def __init__(self, val):
     5         self.val = val
     6         self.left, self.right = None, None
     7 """
     8 import json
     9 class Solution:
    10 
    11     '''
    12     @param root: An object of TreeNode, denote the root of the binary tree.
    13     This method will be invoked first, you should design your own algorithm 
    14     to serialize a binary tree which denote by a root node to a string which
    15     can be easily deserialized by your own "deserialize" method later.
    16     '''
    17     def serialize(self, root):
    18         # write your code here
    19         result = []
    20         queue = [[None, None, root]] if root else []
    21         i = -1
    22         while queue:
    23             node = queue.pop(0)
    24             result.append([node[0], node[1], node[2].val])
    25             i += 1
    26             if node[2].left:
    27                 queue.append([i, 0, node[2].left])
    28             if node[2].right:
    29                 queue.append([i, 1, node[2].right])
    30         return json.dumps(result)
    31 
    32     '''
    33     @param data: A string serialized by your serialize method.
    34     This method will be invoked second, the argument data is what exactly
    35     you serialized at method "serialize", that means the data is not given by
    36     system, it's given by your own serialize method. So the format of data is
    37     designed by yourself, and deserialize it here as you serialize it in 
    38     "serialize" method.
    39     '''
    40     def deserialize(self, data):
    41         # write your code here
    42         result = json.loads(data)
    43         for i in range(len(result)):
    44             temp = result[i]
    45             result[i] = TreeNode(result[i][2])
    46             if not temp[0] is None:
    47                 if temp[1] == 0:
    48                     result[temp[0]].left = result[i]
    49                 if temp[1] == 1:
    50                     result[temp[0]].right = result[i]
    51         return result[0] if result else None
    View Code

    -------------------------------------------------------------------------

    70.binary-tree-level-order-traversal-ii

    给出一棵二叉树,返回其节点值从底向上的层次序遍历(按从叶节点所在层到根节点所在的层遍历,然后逐层从左往右遍历)

     1 """
     2 Definition of TreeNode:
     3 class TreeNode:
     4     def __init__(self, val):
     5         self.val = val
     6         self.left, self.right = None, None
     7 """
     8 
     9 
    10 class Solution:
    11     """
    12     @param root: The root of binary tree.
    13     @return: buttom-up level order in a list of lists of integers
    14     """
    15     def levelOrderBottom(self, root):
    16         # write your code here
    17         result = []
    18         if not root:
    19             return result
    20         queue = [root]
    21         while queue:
    22             size = len(queue)
    23             level = []
    24             for i in range(size):
    25                 node = queue.pop(0)
    26                 level.append(node.val)
    27                 if node.left:
    28                     queue.append(node.left)
    29                 if node.right:
    30                     queue.append(node.right)
    31             result.append(level)
    32         return result[::-1]
    View Code

    17.5.29二刷

     1 """
     2 Definition of TreeNode:
     3 class TreeNode:
     4     def __init__(self, val):
     5         self.val = val
     6         self.left, self.right = None, None
     7 """
     8 
     9 
    10 class Solution:
    11     """
    12     @param root: The root of binary tree.
    13     @return: buttom-up level order in a list of lists of integers
    14     """
    15     def levelOrderBottom(self, root):
    16         # write your code here
    17         if not root:
    18             return []
    19         result = []
    20         queue = [root]
    21         while queue:
    22             size = len(queue)
    23             tmp = []
    24             for i in range(size):
    25                 node = queue.pop(0)
    26                 tmp.append(node.val)
    27                 if node.left:
    28                     queue.append(node.left)
    29                 if node.right:
    30                     queue.append(node.right)
    31             result.append(tmp)
    32         return result[::-1]
    View Code

    -------------------------------------------------------------------------

    71.binary-tree-zigzag-level-order-traversal

    给出一棵二叉树,返回其节点值的锯齿形层次遍历(先从左往右,下一层再从右往左,层与层之间交替进行)

     1 """
     2 Definition of TreeNode:
     3 class TreeNode:
     4     def __init__(self, val):
     5         self.val = val
     6         self.left, self.right = None, None
     7 """
     8 
     9 
    10 class Solution:
    11     """
    12     @param root: The root of binary tree.
    13     @return: A list of list of integer include 
    14              the zig zag level order traversal of its nodes' values
    15     """
    16     def zigzagLevelOrder(self, root):
    17         # write your code here
    18         result = []
    19         if not root:
    20             return result
    21         queue = [root]
    22         flag = True
    23         while queue:
    24             size = len(queue)
    25             level = []
    26             for i in range(size):
    27                 node = queue.pop(0)
    28                 level.append(node.val)
    29                 if node.left:
    30                     queue.append(node.left)
    31                 if node.right:
    32                     queue.append(node.right)
    33             result.append(level if flag else level[::-1])
    34             flag = not flag
    35         return result
    View Code

    17.5.29二刷

     1 """
     2 Definition of TreeNode:
     3 class TreeNode:
     4     def __init__(self, val):
     5         self.val = val
     6         self.left, self.right = None, None
     7 """
     8 
     9 
    10 class Solution:
    11     """
    12     @param root: The root of binary tree.
    13     @return: A list of list of integer include 
    14              the zig zag level order traversal of its nodes' values
    15     """
    16     def zigzagLevelOrder(self, root):
    17         # write your code here
    18         result = []
    19         if not root:
    20             return result
    21         queue = [root]
    22         reverse = False
    23         while queue:
    24             size = len(queue)
    25             tmp = []
    26             for i in range(size):
    27                 node = queue.pop(0)
    28                 tmp.append(node.val)
    29                 if node.left:
    30                     queue.append(node.left)
    31                 if node.right:
    32                     queue.append(node.right)
    33             result.append(tmp if not reverse else tmp[::-1])
    34             reverse = not reverse
    35         return result
    View Code

    -------------------------------------------------------------------------

    120.word-ladder

    给出两个单词(start和end)和一个字典,找到从start到end的最短转换序列

    比如:

    1. 每次只能改变一个字母。
    2. 变换过程中的中间单词必须在字典中出现。
     1 class Solution:
     2     # @param start, a string
     3     # @param end, a string
     4     # @param dict, a set of string
     5     # @return an integer
     6     def ladderLength(self, start, end, dict):
     7         # write your code here
     8         queue = [start]
     9         visited = set([start])
    10         level = 0
    11         dict.add(start)
    12         dict.add(end)
    13         
    14         while queue:
    15             level += 1
    16             size = len(queue)
    17             for i in range(size):
    18                 word = queue.pop(0)
    19                 if word == end:
    20                     return level
    21                 for item in self.find_neighbors(word, dict):
    22                     if item in visited:
    23                         continue
    24                     visited.add(item)
    25                     queue.append(item)
    26         
    27     def find_neighbors(self, word, dict):
    28         result = []
    29         for i in range(len(word)):
    30             code = ord(word[i])
    31             for j in range(97, 123):
    32                 if j == code:
    33                     continue
    34                 string = word[:i] + chr(j) + word[i + 1:]
    35                 if string in dict:
    36                     result.append(string)
    37         return result
    View Code

    17.5.29二刷

     1 class Solution:
     2     # @param start, a string
     3     # @param end, a string
     4     # @param dict, a set of string
     5     # @return an integer
     6     def ladderLength(self, start, end, dict):
     7         # write your code here
     8         if start == end:
     9             return 1
    10         dict = set(dict)
    11         visited = set([start])
    12         queue = [start]
    13         step = 0
    14         while queue:
    15             step += 1
    16             size = len(queue)
    17             for i in range(size):
    18                 word = queue.pop(0)
    19                 for w in self.findNeighbors(word):
    20                     if w == end:
    21                         return step + 1 
    22                     if w in dict and w not in visited:
    23                         visited.add(w)
    24                         queue.append(w)
    25         return 0
    26         
    27         
    28     def findNeighbors(self, word):
    29         result = []
    30         for i in range(len(word)):
    31             for j in range(97, 123):
    32                 result.append(word[:i] + chr(j) + word[i + 1:])
    33         return result
    View Code

    -------------------------------------------------------------------------

    127.topological-sorting

    给定一个有向图,图节点的拓扑排序被定义为:

    • 对于每条有向边A--> B,则A必须排在B之前  
    • 拓扑排序的第一个节点可以是任何在图中没有其他节点指向它的节点  

    找到给定图的任一拓扑排序

     1 # Definition for a Directed graph node
     2 # class DirectedGraphNode:
     3 #     def __init__(self, x):
     4 #         self.label = x
     5 #         self.neighbors = []
     6 
     7 class Solution:
     8     """
     9     @param graph: A list of Directed graph node
    10     @return: A list of graph nodes in topological order.
    11     """
    12     def topSort(self, graph):
    13         # write your code here
    14         result = []
    15         if not graph:
    16             return result
    17             
    18         for node in graph:
    19             for n in node.neighbors:
    20                 if hasattr(n, 'in_degree'):
    21                     n.in_degree += 1
    22                 else:
    23                     n.in_degree = 1
    24         
    25         queue = []            
    26         for node in graph:
    27             if not hasattr(node, 'in_degree') or node.in_degree == 0:
    28                 queue.append(node)
    29         while queue:
    30             node = queue.pop(0)
    31             result.append(node)
    32             for n in node.neighbors:
    33                 n.in_degree -= 1
    34                 if n.in_degree == 0:
    35                     queue.append(n)
    36         return result
    View Code

    17.5.29二刷

     1 # Definition for a Directed graph node
     2 # class DirectedGraphNode:
     3 #     def __init__(self, x):
     4 #         self.label = x
     5 #         self.neighbors = []
     6 
     7 class Solution:
     8     """
     9     @param graph: A list of Directed graph node
    10     @return: A list of graph nodes in topological order.
    11     """
    12     def topSort(self, graph):
    13         # write your code here
    14         map = {}
    15         for node in graph:
    16             map[node.label] = {'parents':0, 
    17                 'children':[n.label for n in node.neighbors], 
    18                 'node':node}
    19         for node in graph:
    20             for c in map[node.label]['children']:
    21                 map[c]['parents'] += 1
    22                 
    23         queue = [key for key in map if map[key]['parents'] == 0]
    24         result = []
    25         while queue:
    26             node = queue.pop(0)
    27             result.append(map[node]['node'])
    28             for c in map[node]['children']:
    29                 map[c]['parents'] -= 1
    30                 if map[c]['parents'] == 0:
    31                     queue.append(c)
    32                     
    33         return result
    View Code

    -------------------------------------------------------------------------

    618.search-graph-nodes

    Given a undirected graph, a node and a target, return the nearest node to given node which value of it is target, return NULL if you can't find.

     1 # Definition for a undirected graph node
     2 # class UndirectedGraphNode:
     3 #     def __init__(self, x):
     4 #         self.label = x
     5 #         self.neighbors = []
     6 
     7 class Solution:
     8     # @param {UndirectedGraphNode[]} graph a list of undirected graph node
     9     # @param {dict} values a dict, <UndirectedGraphNode, (int)value>
    10     # @param {UndirectedGraphNode} node an Undirected graph node
    11     # @param {int} target an integer
    12     # @return {UndirectedGraphNode} a node
    13     def searchNode(self, graph, values, node, target):
    14         # Write your code here
    15         if not graph or not node or not values or target is None:
    16             return None
    17         queue = [node]
    18         while queue:
    19             nd = queue.pop(0)
    20             if values[nd] == target:
    21                 return nd
    22             for neighbor in nd.neighbors:
    23                 queue.append(neighbor)
    24         return None
    View Code

    17.5.30二刷

     1 # Definition for a undirected graph node
     2 # class UndirectedGraphNode:
     3 #     def __init__(self, x):
     4 #         self.label = x
     5 #         self.neighbors = []
     6 
     7 class Solution:
     8     # @param {UndirectedGraphNode[]} graph a list of undirected graph node
     9     # @param {dict} values a dict, <UndirectedGraphNode, (int)value>
    10     # @param {UndirectedGraphNode} node an Undirected graph node
    11     # @param {int} target an integer
    12     # @return {UndirectedGraphNode} a node
    13     def searchNode(self, graph, values, node, target):
    14         # Write your code here
    15         queue = [node]
    16         visited = set([node])
    17         while queue:
    18             node = queue.pop(0)
    19             if values[node] == target:
    20                 return node
    21             for child in node.neighbors:
    22                 if child not in visited:
    23                     visited.add(child)
    24                     queue.append(child)
    View Code

    -------------------------------------------------------------------------

    616.course-schedule-ii

    拓扑排序

     1 class Solution:
     2     # @param {int} numCourses a total of n courses
     3     # @param {int[][]} prerequisites a list of prerequisite pairs
     4     # @return {int[]} the course order
     5     def findOrder(self, numCourses, prerequisites):
     6         # Write your code here
     7         nodes = {}
     8         queue = []
     9         result = []
    10         for i in range(numCourses):
    11             nodes[i] = {
    12                     'pre' : 0,
    13                     'next' : []
    14                 }
    15         for p in prerequisites:
    16             nodes[p[0]]['pre'] += 1
    17             nodes[p[1]]['next'].append(p[0])
    18             
    19         for key in nodes:
    20             if nodes[key]['pre'] == 0:
    21                 queue.append(key)
    22                 
    23         while queue:
    24             node = queue.pop(0)
    25             result.append(node)
    26             for next in nodes[node]['next']:
    27                 nodes[next]['pre'] -= 1
    28                 if nodes[next]['pre'] == 0:
    29                     queue.append(next)
    30                     
    31         return result if len(result) == numCourses else []
    32                 
    33         
    View Code

    17.5.30二刷

     1 class Solution:
     2     # @param {int} numCourses a total of n courses
     3     # @param {int[][]} prerequisites a list of prerequisite pairs
     4     # @return {int[]} the course order
     5     def findOrder(self, numCourses, prerequisites):
     6         # Write your code here
     7         graph = {}
     8         queue = []
     9         result = []
    10         for i in range(numCourses):
    11             graph[i] = {
    12                     'pre' : 0,
    13                     'next' : []
    14                 }
    15         for p in prerequisites:
    16             graph[p[0]]['pre'] += 1
    17             graph[p[1]]['next'].append(p[0])
    18         for i in graph:
    19             if graph[i]['pre'] == 0:
    20                 queue.append(i)
    21                 
    22         # bfs
    23         while queue:
    24             node = queue.pop(0)
    25             result.append(node)
    26             for child in graph[node]['next']:
    27                 graph[child]['pre'] -= 1
    28                 if graph[child]['pre'] == 0:
    29                     queue.append(child)
    30         return result if len(result) == numCourses else []
    31         
    View Code

    -------------------------------------------------------------------------

    611.knight-shortest-path

    Given a knight in a chessboard (a binary matrix with 0 as empty and 1 as barrier) with a source position, find the shortest path to a destination position, return the length of the route. 
    Return -1 if knight can not reached.

     1 # Definition for a point.
     2 # class Point:
     3 #     def __init__(self, a=0, b=0):
     4 #         self.x = a
     5 #         self.y = b
     6 
     7 class Solution:
     8     # @param {boolean[][]} grid a chessboard included 0 (False) and 1 (True)
     9     # @param {Point} source a point
    10     # @param {Point} destination a point
    11     # @return {int} the shortest path 
    12     def shortestPath(self, grid, source, destination):
    13         # Write your code here
    14         row = len(grid)
    15         if row == 0:
    16             return 0
    17         col = len(grid[0])
    18         
    19         jump = -1
    20         visited = [[False for i in range(col)] for j in range(row)]
    21         nbrow = [1, -1, 2, 2, 1, -1, -2, -2]
    22         nbcol = [2, 2, 1, -1, -2, -2, 1, -1]
    23         queue = [(source.x, source.y)]
    24         while queue:
    25             size = len(queue)
    26             jump += 1
    27             for s in range(size):
    28                 (x, y) = queue.pop(0)
    29                 if (x, y) == (destination.x, destination.y):
    30                     return jump
    31                 visited[x][y] = True
    32                 for i in range(8):
    33                     nx = x + nbrow[i]
    34                     ny = y + nbcol[i]
    35                     if nx >= 0 and nx < row and ny >= 0 and ny < col 
    36                         and (not grid[nx][ny]) and (not visited[nx][ny]) 
    37                         and ((nx, ny) not in queue): #最后一个条件非常重要,重复元素不入队
    38                         queue.append((nx, ny))
    39         return -1
    40         
    41         
    42         
    View Code

    17.5.30二刷

     1 # Definition for a point.
     2 # class Point:
     3 #     def __init__(self, a=0, b=0):
     4 #         self.x = a
     5 #         self.y = b
     6 
     7 class Solution:
     8     # @param {boolean[][]} grid a chessboard included 0 (False) and 1 (True)
     9     # @param {Point} source a point
    10     # @param {Point} destination a point
    11     # @return {int} the shortest path 
    12     def shortestPath(self, grid, source, destination):
    13         # Write your code here
    14         m, n = len(grid), len(grid[0])
    15         visited = [[0] * n for i in range(m)]
    16         visited[source.x][source.y] = 1
    17         queue = [source]
    18         step = -1
    19         axis_x = [1, 1, -1, -1, 2, 2, -2, -2]
    20         axis_y = [2, -2, 2, -2, 1, -1, 1, -1]
    21         while queue:
    22             size = len(queue)
    23             step += 1
    24             for i in range(size):
    25                 pos = queue.pop(0)
    26                 if pos.x == destination.x and pos.y == destination.y:
    27                     return step
    28                 for j in range(len(axis_x)):
    29                     n_x, n_y = pos.x + axis_x[j], pos.y + axis_y[j]
    30                     if self.checkPos(grid, visited, n_x, n_y):
    31                         visited[n_x][n_y] = 1
    32                         queue.append(Point(n_x, n_y))
    33         return -1
    34                     
    35     def checkPos(self, grid, visited, x, y):
    36         m, n = len(grid), len(grid[0])
    37         if not (0 <= x < m and 0 <= y < n):
    38             return False
    39         if visited[x][y] == 1:
    40             return False
    41         if grid[x][y] == 1:
    42             return False
    43         return True
    44                 
    45         
    View Code

    -------------------------------------------------------------------------

    598.zombie-in-matrix

    Given a 2D grid, each cell is either a wall 2, a zombie 1 or people 0 (the number zero, one, two).Zombies can turn the nearest people(up/down/left/right) into zombies every day, but can not through wall. How long will it take to turn all people into zombies? Return -1 if can not turn all people into zombies.

     1 class Solution:
     2     # @param {int[][]} grid  a 2D integer grid
     3     # @return {int} an integer
     4     def zombie(self, grid):
     5         # Write your code here
     6         row = len(grid)
     7         if row == 0:
     8             return 0
     9         col = len(grid[0])
    10         
    11         jump = -1
    12         nbrow = [1, -1, 0, 0]
    13         nbcol = [0, 0, 1, -1]
    14         queue = []
    15         for r in range(row):
    16             for c in range(col):
    17                 if grid[r][c] == 1:
    18                     queue.append((r,c))
    19         while queue:
    20             size = len(queue)
    21             jump += 1
    22             for s in range(size):
    23                 (x, y) = queue.pop(0)
    24                 for i in range(4):
    25                     nx = x + nbrow[i]
    26                     ny = y + nbcol[i]
    27                     if nx >= 0 and nx < row and ny >= 0 and ny < col 
    28                         and grid[nx][ny] == 0 and ((nx, ny) not in queue):
    29                         #最后一个条件非常重要,重复元素不入队
    30                         grid[nx][ny] = 1
    31                         queue.append((nx, ny))
    32         for r in range(row):
    33             for c in range(col):
    34                 if grid[r][c] == 0:
    35                     return -1               
    36         return jump
    View Code

    17.5.30二刷

     1 class Solution:
     2     # @param {int[][]} grid  a 2D integer grid
     3     # @return {int} an integer
     4     def zombie(self, grid):
     5         # Write your code here
     6         queue = []
     7         day = 0
     8         cnt = 0
     9         axis_x = [1, -1, 0, 0]
    10         axis_y = [0, 0, 1, -1]
    11         for i in range(len(grid)):
    12             for j in range(len(grid[0])):
    13                 if grid[i][j] == 0:
    14                     cnt += 1
    15                 if grid[i][j] == 1:
    16                     queue.append([i, j])
    17         if cnt == 0:
    18             return day
    19         while queue:
    20             size = len(queue)
    21             day += 1
    22             for i in range(size):
    23                 z = queue.pop(0)
    24                 for i in range(len(axis_x)):
    25                     x, y = z[0] + axis_x[i], z[1] + axis_y[i]
    26                     if self.check(grid, x, y):
    27                         grid[x][y] = 1
    28                         queue.append([x, y])
    29                         cnt -= 1
    30                         if cnt == 0:
    31                             return day
    32         return -1
    33         
    34     def check(self, grid, x, y):
    35         if not (0 <= x < len(grid) and 0 <= y < len(grid[0])):
    36             return False
    37         if grid[x][y] != 0:
    38             return False
    39         return True
    40         
    View Code

    -------------------------------------------------------------------------

    573.build-post-office-ii

    Given a 2D grid, each cell is either a wall 2, an house 1 or empty 0 (the number zero, one, two), find a place to build a post office so that the sum of the distance from the post office to all the houses is smallest.

    Return the smallest sum of distance. Return -1 if it is not possible.

     1 class Solution:
     2     # @param {int[][]} grid a 2D grid
     3     # @return {int} an integer
     4     def shortestDistance(self, grid):
     5         # Write your code here
     6         # 判断当前节点是不是没走过的empty节点
     7         def isVaild(grid, r, c, row, col, visited):
     8             if r >= 0 and r < row and c >= 0 and c < col 
     9                     and grid[r][c] == 0 and (not visited[r][c]):
    10                 return True            
    11             return False 
    12             
    13         row = len(grid)
    14         if row == 0:
    15             return 0
    16         col = len(grid[0])
    17         nbrow = [1, -1, 0, 0]
    18         nbcol = [0, 0, 1, -1]
    19         empty, wall, house, distance = self.initialize(grid, row, col)
    20         for h in house: #对于每个房子BFS
    21             jump = -1 
    22             queue = [h]
    23             # visited distance等辅助数组,要使用最原始的数组
    24             # (每个元素对应一个格子,存各种数据,而不是存格子下标)
    25             # (不要用in查询,增加复杂度)
    26             visited = [[False for c in range(col)] for r in range(row)]
    27             while queue:
    28                 jump += 1
    29                 size = len(queue)
    30                 for s in range(size):
    31                     node = queue.pop(0)
    32                     if grid[node[0]][node[1]] == 0:
    33                         distance[node[0]][node[1]] += jump
    34                     for i in range(4):
    35                         nx = node[0] + nbrow[i]
    36                         ny = node[1] + nbcol[i]
    37                         if isVaild(grid, nx, ny, row, col, visited):
    38                             visited[nx][ny] = True
    39                             queue.append((nx, ny))
    40             for i in range(row):
    41                 for j in range(col):
    42                     if not visited[i][j]:
    43                         # 假如当前empty,存在一个房子无法到达
    44                         # 那么以后邮局不可能选在它上面,路径也不能通过它
    45                         # 标记为墙,以后不需要探测
    46                         grid[i][j] = 2
    47                         distance[i][j] = 99999
    48         result = min([min(l) for l in distance])
    49         return result if result != 99999 else -1
    50              
    51     def initialize(self, grid, row, col):
    52         empty = []
    53         wall = []
    54         house = []
    55         distance = [[0 for c in range(col)] for r in range(row)]
    56         for r in range(row):
    57             for c in range(col):
    58                 if grid[r][c] == 1:
    59                     house.append((r, c))
    60                 elif grid[r][c] == 2:
    61                     wall.append((r, c))
    62                 else:
    63                     empty.append((r, c))
    64         for r, c in wall:
    65             distance[r][c] = 99999
    66         for r, c in house:
    67             distance[r][c] = 99999  
    68         return empty, wall, house, distance
    View Code

    17.5.30二刷

     1 class Solution:
     2     # @param {int[][]} grid a 2D grid
     3     # @return {int} an integer
     4     def shortestDistance(self, grid):
     5         # Write your code here
     6         distance = [[0] * len(grid[0]) for i in range(len(grid))]
     7         houses = []
     8         empties = set([])
     9         axis_x = [1, -1, 0, 0]
    10         axis_y = [0, 0, 1, -1]
    11         for i in range(len(grid)):
    12             for j in range(len(grid[0])):
    13                 if grid[i][j] != 0:
    14                     distance[i][j] = 99999
    15                     if grid[i][j] == 1:
    16                         houses.append((i, j))
    17                 else:
    18                     empties.add((i, j))
    19                         
    20         for h in houses:
    21             queue = [h]
    22             visited = set(queue)
    23             step = -1
    24             while queue:
    25                 step += 1
    26                 size = len(queue)
    27                 for i in range(size):
    28                     pos = queue.pop(0)
    29                     distance[pos[0]][pos[1]] += step
    30                     for j in range(len(axis_x)):
    31                         x, y = pos[0] + axis_x[j], pos[1] + axis_y[j]
    32                         if self.check(grid, distance, visited, x, y):
    33                             visited.add((x, y))
    34                             queue.append((x, y))
    35             diff = empties - visited
    36             for d in diff:
    37                 distance[d[0]][d[1]] = 99999
    38         m = min([min(line) for line in distance])
    39         return m if m < 99999 else -1
    40             
    41     def check(self, grid, distance, visited, x, y):
    42         if not (0 <= x < len(grid) and 0 <= y < len(grid[0])):
    43             return False
    44         return grid[x][y] == 0 and distance[x][y] < 99999 and (x, y) not in visited
    45             
    View Code

    -------------------------------------------------------------------------

    433.number-of-islands

    给一个01矩阵,求不同的岛屿的个数。

    0代表海,1代表岛,如果两个1相邻,那么这两个1属于同一个岛。我们只考虑上下左右为相邻。

     1 class Solution:
     2     # @param {boolean[][]} grid a boolean 2D matrix
     3     # @return {int} an integer
     4     def numIslands(self, grid):
     5         # Write your code here
     6         self.row = len(grid)
     7         if self.row == 0:
     8             return 0
     9         self.col = len(grid[0])
    10         
    11         self.visited = [[False for i in range(self.col)] for j in range(self.row)]
    12         count = 0
    13         for r in range(self.row):
    14             for c in range(self.col):
    15                 if self.check(grid, r, c):
    16                     self.bfs(grid, r, c)
    17                     count += 1
    18         return count
    19         
    20     def check(self, grid, r, c):
    21         if r >= 0 and r < self.row and c >= 0 and c < self.col 
    22             and grid[r][c] and (not self.visited[r][c]):
    23             return True
    24         return False
    25         
    26     def bfs(self, grid, r, c):
    27         nbrow = [1, -1, 0, 0]
    28         nbcol = [0, 0, 1, -1]
    29         queue = [(r, c)]
    30         while queue:
    31             (x, y) = queue.pop(0)
    32             self.visited[x][y] = True
    33             for i in range(4):
    34                 nx = x + nbrow[i]
    35                 ny = y + nbcol[i]
    36                 if self.check(grid, nx, ny):
    37                     queue.append((nx, ny))
    View Code

    17.5.31二刷

     1 class Solution:
     2     # @param {boolean[][]} grid a boolean 2D matrix
     3     # @return {int} an integer
     4     def numIslands(self, grid):
     5         # Write your code here
     6         if not grid or not grid[0]:
     7             return 0
     8         m, n = len(grid), len(grid[0])
     9         visited = [[0] * n for i in range(m)]
    10         result = 0
    11         queue = []
    12         for i in range(m):
    13             for j in range(n):
    14                 if grid[i][j] == 1 and visited[i][j] == 0:
    15                     visited[i][j] = 1
    16                     result += 1
    17                     queue.append((i, j))
    18                     self.bfs(queue, grid, visited)
    19         return result
    20         
    21     def bfs(self, queue, grid, visited):
    22         axis_x = [1, -1, 0, 0]
    23         axis_y = [0, 0, 1, -1]
    24         
    25         while queue:
    26             node = queue.pop(0)
    27             for i in range(4):
    28                 x = node[0] + axis_x[i]
    29                 y = node[1] + axis_y[i]
    30                 if self.check(grid, visited, x, y):
    31                     visited[x][y] = 1
    32                     queue.append((x, y))
    33                     
    34     def check(self, grid, visited, x, y):
    35         if not (0 <= x < len(grid) and 0 <= y < len(grid[0])):
    36             return False
    37         return grid[x][y] == 1 and visited[x][y] == 0
    38             
    39         
    View Code

    -------------------------------------------------------------------------

    178.graph-valid-tree

    给出 n 个节点,标号分别从 0 到 n - 1 并且给出一个 无向 边的列表 (给出每条边的两个顶点), 写一个函数去判断这张`无向`图是否是一棵树

     1 class Solution:
     2     # @param {int} n an integer
     3     # @param {int[][]} edges a list of undirected edges
     4     # @return {boolean} true if it's a valid tree, or false
     5     def validTree(self, n, edges):
     6         # Write your code here
     7         if not n or edges is None:
     8             return False
     9         if len(edges) != n - 1:
    10             return False
    11             
    12         graph = []
    13         for i in range(n):
    14             graph.append(set([]))
    15         for edge in edges:
    16             graph[edge[0]].add(edge[1])
    17             graph[edge[1]].add(edge[0])
    18             
    19         queue = [0]
    20         node_set = set([])
    21         
    22         while queue:
    23             key = queue.pop(0)
    24             node_set.add(key)
    25             for node in graph[key]:
    26                 if node not in node_set:
    27                     queue.append(node)
    28                     
    29         return len(node_set) == n
    View Code

    17.5.31二刷

    if len(edges) != n - 1:
        return False

    这个条件非常重要,排除连通但是有环的情况。接下来只需要检查是不是每个节点都visited了

     1 class Solution:
     2     # @param {int} n an integer
     3     # @param {int[][]} edges a list of undirected edges
     4     # @return {boolean} true if it's a valid tree, or false
     5     def validTree(self, n, edges):
     6         # Write your code here
     7         if len(edges) != n - 1:
     8             return False
     9         d = {}
    10         v = [0] * n
    11         for i in range(n):
    12             d[i] = set([])
    13 
    14         for e in edges:
    15             d[e[0]].add(e[1])
    16             d[e[1]].add(e[0])
    17             
    18         queue = [0]
    19         v[0] = 1
    20         while queue:
    21             p = queue.pop(0)
    22             for pp in d[p]:
    23                 if v[pp] == 0:
    24                     v[pp] = 1
    25                     queue.append(pp)
    26         return sum(v) == n
    View Code

    -------------------------------------------------------------------------

    242.convert-binary-tree-to-linked-lists-by-depth

    给一棵二叉树,设计一个算法为每一层的节点建立一个链表。也就是说,如果一棵二叉树有D层,那么你需要创建D条链表。

     1 """
     2 Definition of TreeNode:
     3 class TreeNode:
     4     def __init__(self, val):
     5         this.val = val
     6         this.left, this.right = None, None
     7 Definition for singly-linked list.
     8 class ListNode:
     9     def __init__(self, x):
    10         self.val = x
    11         self.next = None
    12 """
    13 class Solution:
    14     # @param {TreeNode} root the root of binary tree
    15     # @return {ListNode[]} a lists of linked list
    16     def binaryTreeToLists(self, root):
    17         # Write your code here
    18         # bfs
    19         results = []
    20         if not root:
    21             return []
    22         queue = [root]
    23         while queue:
    24             # bfs for each level
    25             size = len(queue)
    26             # header for a linked list
    27             header = ListNode( -1)
    28             result = header
    29             for i in range(size):
    30                 ele = queue.pop(0)
    31                 result.next = ListNode(ele.val)
    32                 result = result.next
    33                 if ele.left:
    34                     queue.append(ele.left)
    35                 if ele.right:
    36                     queue.append(ele.right)
    37             results.append(header.next)
    38         return results
    39         
    View Code

    17.5.31二刷

     1 """
     2 Definition of TreeNode:
     3 class TreeNode:
     4     def __init__(self, val):
     5         this.val = val
     6         this.left, this.right = None, None
     7 Definition for singly-linked list.
     8 class ListNode:
     9     def __init__(self, x):
    10         self.val = x
    11         self.next = None
    12 """
    13 class Solution:
    14     # @param {TreeNode} root the root of binary tree
    15     # @return {ListNode[]} a lists of linked list
    16     def binaryTreeToLists(self, root):
    17         # Write your code here
    18         level = []
    19         result = []
    20         if not root:
    21             return result
    22         queue = [root]
    23         while queue:
    24             size = len(queue)
    25             tmp = []
    26             for i in range(size):
    27                 tn = queue.pop(0)
    28                 tmp.append(tn.val)
    29                 if tn.left:
    30                     queue.append(tn.left)
    31                 if tn.right:
    32                     queue.append(tn.right)
    33             level.append(tmp)
    34             
    35         for l in level:
    36             head = ListNode(0)
    37             cur = head
    38             for i in l:
    39                 cur.next = ListNode(i)
    40                 cur = cur.next
    41             result.append(head.next)
    42             
    43         return result
    44             
    View Code

    -------------------------------------------------------------------------

    624.remove-substrings

    Given a string s and a set of n substrings. You are supposed to remove every instance of those n substrings from s so that s is of the minimum length and output this minimum length.

     1 class Solution:
     2     # @param {string} s a string
     3     # @param {set} dict a set of n substrings
     4     # @return {int} the minimum length
     5     def minLength(self, s, dict):
     6         # Write your code here
     7         if not s:
     8             return 0
     9         queue = [s]
    10         visited = set([])
    11         min_len = sys.maxint
    12         while queue:
    13             ele = queue.pop(0)
    14             for string in dict:
    15                 found = ele.find(string)
    16                 # to find all the string in ele
    17                 while found != -1:
    18                     new_s = ele[:found] + ele[found + len(string):]
    19                     if new_s not in visited:
    20                         visited.add(new_s)
    21                         queue.append(new_s)
    22                         if len(new_s) < min_len:
    23                             min_len = len(new_s)
    24                     found = ele.find(string, found + 1)
    25         return min_len
    26         
    View Code

    17.5.31二刷

    注意while found != -1:

    要将字符串中删除子串的所有可能性尝试一遍,比如"abcabd", ["ab","abcd"] 按"ab"删除出两个子串"cabd","abcd"

     1 class Solution:
     2     # @param {string} s a string
     3     # @param {set} dict a set of n substrings
     4     # @return {int} the minimum length
     5     def minLength(self, s, dict):
     6         # Write your code here
     7         if not s:
     8             return 0
     9         queue = [s]
    10         visited = set([])
    11         min_len = len(s)
    12         while queue:
    13             ele = queue.pop(0)
    14             for string in dict:
    15                 found = ele.find(string)
    16                 # to find all the string in ele
    17                 while found != -1:
    18                     new_s = ele[:found] + ele[found + len(string):]
    19                     if new_s not in visited:
    20                         visited.add(new_s)
    21                         queue.append(new_s)
    22                         if len(new_s) < min_len:
    23                             min_len = len(new_s)
    24                     found = ele.find(string, found + 1)
    25         return min_len
    View Code

    -------------------------------------------------------------------------

    137.clone-graph

    克隆一张无向图,图中的每个节点包含一个 label 和一个列表 neighbors

     1 # Definition for a undirected graph node
     2 # class UndirectedGraphNode:
     3 #     def __init__(self, x):
     4 #         self.label = x
     5 #         self.neighbors = []
     6 class Solution:
     7     # @param node, a undirected graph node
     8     # @return a undirected graph node
     9     def __init__(self):
    10         self.dict = {}
    11         
    12     def cloneGraph(self, node):
    13         # write your code here
    14         if not node:
    15             return None
    16         nodes = self.bfs(node)
    17         
    18         map_new_node = {}
    19         for n in nodes:
    20             map_new_node[n] = UndirectedGraphNode(n.label)
    21             
    22         for n in nodes:
    23             for l in n.neighbors:
    24                 map_new_node[n].neighbors.append(map_new_node[l])
    25             
    26         return map_new_node[node]
    27         
    28     def bfs(self, node):
    29         result = []
    30         if not node:
    31             return result
    32             
    33         queue = [node]
    34         node_set = set([])
    35         while queue:
    36             
    37             n = queue.pop(0)
    38             if n in node_set:
    39                 continue
    40             result.append(n)
    41             node_set.add(n)
    42             for l in n.neighbors:
    43                 queue.append(l)
    44                     
    45         return result
    View Code

    17.5.31二刷

     1 # Definition for a undirected graph node
     2 # class UndirectedGraphNode:
     3 #     def __init__(self, x):
     4 #         self.label = x
     5 #         self.neighbors = []
     6 class Solution:
     7     # @param node, a undirected graph node
     8     # @return a undirected graph node
     9     def __init__(self):
    10         self.dict = {}
    11         
    12     def cloneGraph(self, node):
    13         # write your code here
    14         if not node:
    15             return
    16         
    17         self.dict[node.label] = UndirectedGraphNode(node.label)
    18         queue = [node]
    19         
    20         while queue:
    21             n = queue.pop(0)
    22             for nn in n.neighbors:
    23                 if nn.label not in self.dict:
    24                     queue.append(nn)
    25                     self.dict[nn.label] = UndirectedGraphNode(nn.label)
    26                 self.dict[n.label].neighbors.append(self.dict[nn.label])
    27             
    28             
    29         return self.dict[node.label]
    View Code

    -------------------------------------------------------------------------

    531.six-degrees

    现在给你一个友谊关系,查询两个人可以通过几步相连,如果不相连返回 -1

     1 # Definition for Undirected graph node
     2 # class UndirectedGraphNode:
     3 #     def __init__(self, x):
     4 #         self.label = x
     5 #         self.neighbors = []
     6 
     7 class Solution:
     8     '''
     9     @param {UndirectedGraphNode[]} graph a list of Undirected graph node
    10     @param {UndirectedGraphNode} s, t two Undirected graph nodes
    11     @return {int} an integer
    12     '''
    13     def sixDegrees(self, graph, s, t):
    14         # Write your code here
    15         if not graph or not s or not t:
    16             return -1
    17             
    18         queue = [s]
    19         steps = 0
    20         visited = set([s])
    21         
    22         while queue:
    23             size = len(queue)
    24             for i in range(size):
    25                 node = queue.pop(0)
    26                 if node == t:
    27                     return steps
    28                 for neighbor in node.neighbors:
    29                     if neighbor not in visited:
    30                         queue.append(neighbor)
    31                         visited.add(neighbor)
    32             steps += 1
    33         return -1
    View Code

    17.5.31二刷

     1 # Definition for Undirected graph node
     2 # class UndirectedGraphNode:
     3 #     def __init__(self, x):
     4 #         self.label = x
     5 #         self.neighbors = []
     6 
     7 class Solution:
     8     '''
     9     @param {UndirectedGraphNode[]} graph a list of Undirected graph node
    10     @param {UndirectedGraphNode} s, t two Undirected graph nodes
    11     @return {int} an integer
    12     '''
    13     def sixDegrees(self, graph, s, t):
    14         # Write your code here
    15         if not graph or not s or not t:
    16             return -1
    17             
    18         queue = [s]
    19         steps = 0
    20         visited = set([s])
    21         
    22         while queue:
    23             size = len(queue)
    24             for i in range(size):
    25                 node = queue.pop(0)
    26                 if node == t:
    27                     return steps
    28                 for neighbor in node.neighbors:
    29                     if neighbor not in visited:
    30                         queue.append(neighbor)
    31                         visited.add(neighbor)
    32             steps += 1
    33         return -1
    View Code

    -------------------------------------------------------------------------

    605.sequence-reconstruction

    判断是否序列 org 能唯一地由 seqs重构得出. org是一个由从1到n的正整数排列而成的序列,1 ≤ n ≤ 10^4。 重构表示组合成seqs的一个最短的父序列 (意思是,一个最短的序列使得所有 seqs里的序列都是它的子序列). 
    判断是否有且仅有一个能从 seqs重构出来的序列,并且这个序列是org

    注意点:

    拓扑排序,一个点只能让一个next入队

    最后比较是否都找到了

     1 class Solution:
     2     # @param {int[]} org a permutation of the integers from 1 to n
     3     # @param {int[][]} seqs a list of sequences
     4     # @return {boolean} true if it can be reconstructed only one or false
     5     def sequenceReconstruction(self, org, seqs):
     6         # Write your code here
     7         from collections import defaultdict
     8         edges = defaultdict(list)
     9         indegrees = defaultdict(int)
    10         nodes = set()
    11         for seq in seqs:
    12             nodes |= set(seq)
    13             for i in xrange(len(seq)):
    14                 if i == 0:
    15                     indegrees[seq[i]] += 0
    16                 if i < len(seq) - 1:
    17                     edges[seq[i]].append(seq[i + 1])
    18                     indegrees[seq[i + 1]] += 1
    19 
    20         cur = [k for k in indegrees if indegrees[k] == 0]
    21         res = []
    22 
    23         while len(cur) == 1:
    24             cur_node = cur.pop()
    25             res.append(cur_node)
    26             for node in edges[cur_node]:
    27                 indegrees[node] -= 1
    28                 if indegrees[node] == 0:
    29                     cur.append(node)
    30         if len(cur) > 1:
    31             return False
    32         return len(res) == len(nodes) and res == org
    View Code

    17.6.8 二刷

     1 class Solution:
     2     # @param {int[]} org a permutation of the integers from 1 to n
     3     # @param {int[][]} seqs a list of sequences
     4     # @return {boolean} true if it can be reconstructed only one or false
     5     def sequenceReconstruction(self, org, seqs):
     6         # Write your code here
     7         if not org and (not seqs or not seqs[0]):
     8             return True
     9         map = {}
    10         queue = []
    11         rebulid = []
    12         for seq in seqs:
    13             if seq:
    14                 map.setdefault(seq[0], {"pre":0, "next":set([])})
    15             for i in range(1, len(seq)):
    16                 map.setdefault(seq[i], {"pre":0, "next":set([])})
    17                 if seq[i] not in map[seq[i - 1]]["next"]:
    18                     map[seq[i]]["pre"] += 1
    19                     map[seq[i - 1]]["next"].add(seq[i])
    20             
    21         for key in map:
    22             if map[key]["pre"] == 0:
    23                 queue.append(key)
    24                 
    25         if len(queue) != 1:
    26             return False
    27             
    28         while queue:
    29             node = queue.pop(0)
    30             rebulid.append(node)
    31             flag = False
    32             for next in map[node]["next"]:
    33                 map[next]["pre"] -= 1
    34                 if map[next]["pre"] == 0:
    35                     if not flag:
    36                         flag = True
    37                         queue.append(next)
    38                     else:
    39                         return False
    40         return rebulid == org
    View Code

    -------------------------------------------------------------------------

    431.connected-component-in-undirected-graph

    找出无向图中所有的连通块。

    图中的每个节点包含一个label属性和一个邻接点的列表。(一个无向图的连通块是一个子图,其中任意两个顶点通过路径相连,且不与整个图中的其它顶点相连。)

     1 # Definition for a undirected graph node
     2 # class UndirectedGraphNode:
     3 #     def __init__(self, x):
     4 #         self.label = x
     5 #         self.neighbors = []
     6 class Solution:
     7     # @param {UndirectedGraphNode[]} nodes a array of undirected graph node
     8     # @return {int[][]} a connected set of a undirected graph
     9     def connectedSet(self, nodes):
    10         # Write your code here
    11         queue = []
    12         visited = set([])
    13         results = []
    14         
    15         for node in nodes:
    16             if node not in visited:
    17                 visited.add(node)
    18                 queue.append(node)
    19                 result = [node.label]    
    20                 while queue:
    21                     item = queue.pop(0)
    22                     for neighbor in item.neighbors:
    23                         if neighbor not in visited:
    24                             queue.append(neighbor)
    25                             visited.add(neighbor)
    26                             result.append(neighbor.label)
    27                 results.append(sorted(result))
    28         return results
    29             
    View Code

    17.6.8 二刷

     1 # Definition for a undirected graph node
     2 # class UndirectedGraphNode:
     3 #     def __init__(self, x):
     4 #         self.label = x
     5 #         self.neighbors = []
     6 class Solution:
     7     # @param {UndirectedGraphNode[]} nodes a array of undirected graph node
     8     # @return {int[][]} a connected set of a undirected graph
     9     def connectedSet(self, nodes):
    10         # Write your code here
    11         result = []
    12         not_visited = set([])
    13         for n in nodes:
    14             not_visited.add(n)
    15             
    16         while not_visited:
    17             next = None
    18             for i in not_visited:
    19                 next = i
    20                 break
    21             queue = [next]
    22             not_visited.remove(next)
    23             tmp = []
    24             while queue:
    25                 node = queue.pop(0)
    26                 tmp.append(node.label)
    27                 for n in node.neighbors:
    28                     if n in not_visited:
    29                         queue.append(n)
    30                         not_visited.remove(n)
    31             result.append(sorted(tmp))
    32         return result
    33             
    View Code

    -------------------------------------------------------------------------

  • 相关阅读:
    c#队列的实现
    c#队列的实现
    C# 自定义控件制作和使用实例(winform)
    常见的位运算
    Clock()函数简单使用(C库函数)
    Python全局变量的简单使用
    PyQt5+Caffe+Opencv搭建人脸识别登录界面
    python3+pyqt5+opencv3简单使用
    OpenCV实现人脸检测
    opencv 截图并保存
  • 原文地址:https://www.cnblogs.com/zcy-backend/p/6675158.html
Copyright © 2020-2023  润新知