参考:
题目:统计一个数字在排序数组中出现的次数。例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4。
二分查找算法:
GetFirstK用于寻找第一个k出现的位置;
GetLastK用于寻找最后一个k出现的位置;思路与上述类似。
GetFirstK和GetLastK都是用二分查找法在数组中查找一个合乎要求的数字,它们的时间复杂度都是O(logn),因此GetNumberOfK的总的时间复杂度也只有O(logn)。
# -*- coding:utf-8 -*-
class Solution:
def GetNumberOfK(self, data, k):
if data == [] or not k:
return 0
length = len(data)
first = self.GetFirstK(data, k, 0, length-1)
last = self.GetLastK(data, k, 0, length-1)
return last-first+1 if first>-1 and last>-1 else 0
def GetFirstK(self, data, k, start, end):
if start>end:
return -1
mid = int((start + end)/2)
if data[mid]<k:
start = mid + 1
elif data[mid]==k:
if mid>0 and data[mid-1]==k:
end = mid - 1
else:
return mid
else:
end = mid - 1
return self.GetFirstK(data, k, start, end)
def GetLastK(self, data, k, start, end):
if start>end:
return -1
mid = int((start + end)/2)
if data[mid]<k:
start = mid+1
elif data[mid]==k:
if mid<end and data[mid+1]==k:
start = mid+1
else:
return mid
else:
end = mid - 1
return self.GetLastK(data, k, start, end)
题目一:输入一棵二叉树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
复杂度分析:
class Solution(object):
def maxDepth(self, root):
if root is None:
return 0
else:
leftD = self.maxDepth(root.left)
rightD = self.maxDepth(root.right)
return max(leftD, rightD)+1
非递归版本:
使用栈存储已遍历节点和其对应的深度。
复杂度分析:
class Solution(object):
def maxDepth(self, root):
stack = []
if root is not None:
stack.append((1, root))
else:
return 0
depth = 0
while stack:
# d, node = stack.pop()
# depth = max(depth, d)
# if node.left:
# stack.append((d+1, node.left))
# if node.right:
# stack.append((d+1, node.right))
#### 减少了判断条件,更快,
current_depth, root = stack.pop()
if root is not None:
# 当本次弹出的节点非空时,才更新最大深度
depth = max(depth, current_depth)
stack.append((current_depth + 1, root.left))
stack.append((current_depth + 1, root.right))
return depth
输入一棵二叉树的根结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
递归版本的实现:
class Solution(object):
def maxDepth(self, root):
if root is None:
return 0
else:
leftD = self.maxDepth(root.left)
rightD = self.maxDepth(root.right)
return max(leftD, rightD)+1
def isBalanced(self, root):
if root is None:
return True
if abs(self.maxDepth(root.left)-self.maxDepth(root.right))>1:
return False
else:
return self.isBalanced(root.left) and self.isBalanced(root.right)
题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
# -*- coding:utf-8 -*-
class Solution:
def partition(self,array):
n = 0
for i in array:
n ^= i
# 找到异或结果中,最左边的1bit位的位置
start = 0
while n & 1 == 0 and start <= 32:
start += 1
n = n >> 1
arrayA, arrayB = 0, 0
for i in array:
# 判断a在start位上是否为1
# 直接对找到的数字进行异或,得到最终所求数字
if (i >> start)&1 == 1:
arrayA ^= i
else:
arrayB ^= i
return arrayA, arrayB
# 返回[a,b] 其中ab是出现一次的两个数字
def FindNumsAppearOnce(self, array):
if array == [] or len(array)<2:
return
elif len(array) == 2:
return array
return self.partition(array)
**题目一:**输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,输出任意一对即可。
题目二:输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1~5、4~6和7~8。
定义两个序列指针,small与big,small指向较小数字即序列的开头,big指向较大数字即序列的结尾;
# -*- coding:utf-8 -*-
class Solution:
def FindContinuousSequence(self, tsum):
if tsum <= 2:
return []
small, big = 1, 2
cur_sum = small + big
ans = []
# 定义中间数字
middle = (tsum + 1) >> 1
# while big < tsum:
# 终止条件
while small < middle:
if cur_sum == tsum:
ans.append(list(range(small,big+1)))
cur_sum -= small
small += 1
elif cur_sum < tsum:
big += 1
cur_sum += big
else:
cur_sum -= small
small += 1
return ans
**题目一:**输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。
先使用s.split(' ')
将字符串分成多个单词,再使用 ' '.join(l[::-1])
将分开的单词列表,按照从后到前的顺序连接起来,即可得到所求。
# 直接利用Python的语句进行字符串的翻转
def ReverseSentence2(self, s):
l = s.split(' ')
return ' '.join(l[::-1])
**题目二:**字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如输入字符串"abcdefg"和数字2,该函数将返回左旋转2位得到的结果"cdefgab"。
将前半段和后半段分别反转后,交换两段的位置即可。
# -*- coding:utf-8 -*-
class Solution:
def LeftRotateString(self, s, n):
if len(s) <= 0 or len(s) < n or n < 0:
return ''
strList= list(s)
# 翻转字符串
self.Reverse(strList)
length = len(s)
pivot = length - n
frontList = self.Reverse(strList[:pivot])
behindList = self.Reverse(strList[pivot:])
resultStr = ''.join(frontList) + ''.join(behindList)
return resultStr
def Reverse(self, alist):
if alist == None or len(alist) <= 0:
return ''
startIndex = 0
endIndex = len(alist) - 1
# 从数组的两端开始,依次交换数组元素,直到比较的对象位于中间为止
while startIndex < endIndex:
alist[startIndex], alist[endIndex] = alist[endIndex], alist[startIndex]
startIndex += 1
endIndex -= 1
return alist