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