问题:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
算法思想:我们知道每一行都是递增排序的,每一列也是从上到下递增排序的,所以左上角的数是最小的,而右下角的数是最大的
1、选取右上角的数;
2,、判断比较右上角的数和传入的数值的大小,如果等于该参数的值,查找结束;
3、如果大于参数,则可以把这一列剔除;
4、如果小于参数,就剔除该数值所在的行
# -*- coding:utf-8 -*-
class Solution:
def Find(self, target, array):
n=len(array)
flag='false'
for i in range(n):
if target in array[i]:
flag='true'
break
return flag
while True:
try:
S = Solution()
L=list(eval(raw_input()))
array=L[1]
target=L[0]
print(S.Find(target, array))
except:
break
问题:请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
算法思想1:开辟新的空间,从前往后替换:
# -*- coding:utf-8 -*-
class Solution:
# s 源字符串
def replaceSpace(self, s):
# write code here
if len(s)<=0:
return s
result=""
for i in s:
if i.strip():
result+=i
else:
result+="%20"
return result
算法思想2:
在原有的字符串中修改:从后往前添加,每个字符只需移动一次,遇到空格,替换%20,效率高,移动次数少;
先计算出原有的字符串空格的个数,扩展原有字符串长度,新长度=原有长度+空格个数*2,往后移动字符,遇到空格就替换
问题:输入一个链表,从尾到头打印链表每个节点的值。
算法思想:转换成list,然后倒序输出,或者使用栈的思想,先进后出
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
# write code here
newlist=[]
while listNode:
newlist.append(listNode.val)
listNode=listNode.next
return newlist[::-1]
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
算法思想:递归实现
1.根据前序找到根节点;
2.找到根节点在中序中的位置;
3.截取左右子树;
4.左右字数分别递归调用;
5.递归返回节点值
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回构造的TreeNode根节点
def reConstructBinaryTree(self, pre, tin):
# write code here
if len(pre)==0:
return None
if len(pre)==1:
return TreeNode(pre[0])
else:
root=TreeNode(pre[0])
post=tin.index(pre[0])
root.left=self.reConstructBinaryTree(pre[1:post+1],tin[:post])
root.right=self.reConstructBinaryTree(pre[post+1:],tin[post+1:])
return root
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.stack1=[]
self.stack2=[]
def push(self, node):
# write code here
self.stack1.append(node)
def pop(self):
# return xx
if self.stack2==[]:
while self.stack1:
self.stack2.append(self.stack1.pop())
return self.stack2.pop()
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
算法思想:二分查找
# -*- coding:utf-8 -*-
class Solution:
def minNumberInRotateArray(self, rotateArray):
# write code here
length=len(rotateArray)
if length<=0 or rotateArray==None:
return 0
if length==1:
return rotateArray[0]
left,right=0,length-1
while left<=right:
mid=(left+right)>>1
if rotateArray[mid]>rotateArray[right]:
left=mid+1
print(left)
elif rotateArray[mid]else:
right-=1
if left>=right:
break
return rotateArray[left]
现在要求输入一个整数n,请你输出斐波那契数列的第n项。
算法思想一:使用递归:但是如果f(n)=f(n-1)+f(n-2),这样从上往下递归计算的话,会有很多重复的节点,而节点会随着n的增大急剧而增多,意味着计算量急剧增加。
算法思想二:通过循环实现,从f0+f1开始,算出f(2),再有f(1)+f(2)算出f(3),以此类推,算出第n项, 即从下往上计算,每次保存中间列的结果,这样的事件复杂度为O(n)
# -*- coding:utf-8 -*-
class Solution:
def jumpFloorII(self, number):
# write code here
if number <= 0:
return 0
else:
return pow(2,number-1)
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
算法思想:依然是斐波那切数列问题,当跳一节台阶时还有n-1个台阶,当第一次跳两个台阶时,还有n-2个台阶要跳。同样转化为斐波那契数列问题。
# -*- coding:utf-8 -*-
class Solution:
def jumpFloor(self, number):
if number <= 0:
return 1
elif number <= 2:
return number
else:
f1,f2 = 1,2
for i in xrange(2,number+1):
f1,f2=f2,f1+f2
return f1
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
算法思想:依然是斐波那切数列问题
当n = 1 时, 只有一种跳法,即1阶跳:Fib(1) = 1;
当n = 2 时, 有两种跳的方式,一阶跳和二阶跳:Fib(2) = Fib(1) + Fib(0) = 2;
当n = 3 时,有三种跳的方式,第一次跳出一阶后,后面还有Fib(3-1)中跳法; 第一次跳出二阶后,后面还有Fib(3-2)中跳法;第一次跳出三阶后,后面还有Fib(3-3)中跳法
Fib(3) = Fib(2) + Fib(1)+Fib(0)=4;
当n = n 时,共有n种跳的方式,第一次跳出一阶后,后面还有Fib(n-1)中跳法; 第一次跳出二阶后,后面还有Fib(n-2)中跳法……………………..第一次跳出n阶后, 后面还有 Fib(n-n)中跳法.
Fib(n) = Fib(n-1)+Fib(n-2)+Fib(n-3)+……….+Fib(n-n)=Fib(0)+Fib(1)+Fib(2)+…….+Fib(n-1)
又因为Fib(n-1)=Fib(0)+Fib(1)+Fib(2)+…….+Fib(n-2)
两式相减得:Fib(n)-Fib(n-1)=Fib(n-1) =====》 Fib(n) = 2*Fib(n-1) n >= 2
# -*- coding:utf-8 -*-
class Solution:
def jumpFloorII(self, number):
# write code here
if number <= 0:
return 0
else:
return pow(2,number-1)
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
算法思想:当第一步是竖着放,右边还剩n-1个区域,当第一步横着放时,左下角应必须横着放,右边还剩n-2个区域,可以看出这仍斐波那切数列问题f(n)=f(n-1)+f(n-2)
# -*- coding:utf-8 -*-
class Solution:
def rectCover(self, number):
# write code here
a,b=0,1
result=0
for i in range(number):
result=a+b
a=b
b=result
return result
问题:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
算法思想一:
定义一个flag=1,和数字n做与运算,如果结果为1,则个数count+=1,然后flag做右移位移运算,得到的数在于n做与运算,知道最后;这种算法对于32位的整数就要循环32次
# -*- coding:utf-8 -*-
class Solution:
def NumberOf1(self, n):
# write code here
count=0
flag=1
while flag<2**32:
if n & flag:
count+=1
flag=flag << 1
return count
算法思想二:
我们知道一个整数减去1,他的二进制最右边的1的左边的数字不变,右边的数字1变成了0,数字0变成了1,;基于这个思想我们可以把一个数和它减去1之后做与运算,亦可以得出结果
# -*- coding:utf-8 -*-
class Solution:
def NumberOf1(self, n):
# write code here
count=0
if n<0:
n=n&0xFFFFFFFF #把负号去掉,如果负号在后面会陷入死循环
return bin(n).count('1')
while n:
count+=1
n = n & (n-1)
return count
举一反三:
问题:给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
方法一:直接计算
#-*- coding:utf-8 -*-
class Solution:
def Power(self, base, exponent):
# write code here
if base==0:
return False
if exponent==0 or base==1:
return 1
if exponent==1:
return base
result=1.0
for i in range(abs(exponent)):
result *= base
if exponent<0:
result=1.0/result
return result
方法二:判断exponent次方是偶数还是奇数
# -*- coding:utf-8 -*-
class Solution:
def Power(self, base, exponent):
# write code here
flag=0
if exponent<0:
flag=1
exponent=abs(exponent)
if base==0:
return False
if exponent==0 or base==1:
return 1
if exponent==1:
return base
result=self.Power(base,exponent >> 1) #这里使用右移运算来代替除2
result*=result
if (exponent & 1)==1: #这里使用位与运算来代替求余
result *= base
if flag:
result=1.0/result
return result
问题:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分。
# -*- coding:utf-8 -*-
class Solution:
def reOrderArray(self, array):
# write code here
beginInex=0
endIndex=len(array)-1
print(endIndex)
while beginInex while beginInex and ((array[beginInex] & 1) !=0): #说明他是奇数
beginInex+=1
while beginInex and ((array[endIndex] & 1)==0): #偶数
endIndex-=1
if beginInexreturn array
如果在上面的基础上,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
算法思想:开辟新的空间
# -*- coding:utf-8 -*-
class Solution:
def reOrderArray(self, array):
# write code here
if len(array)<1 or not array:
return array
result=[]
for i in range(len(array)):
if (array[i] & 1) !=0:
result.append(array[i])
for i in range(len(array)):
if (array[i] & 1) ==0:
result.append(array[i])
return result
# -*- coding:utf-8 -*-
from collections import deque
class Solution:
def reOrderArray(self, array):
# write code here
if len(array)<1 or not array:
return array
result=deque()
for i in range(len(array)):
if (array[len(array)-i-1] & 1) !=0:
result.appendleft(array[len(array)-i-1])
if (array[i] & 1) ==0:
result.append(array[i])
return result
问题:输入一个链表,输出该链表中倒数第k个结点。
算法思想一:定义连个指针,当第一个指针走了k步之后,第二个指针开始走,当第一个指针走到最后时,第二个指针的位置就是倒数第k个位置
# -*- coding:utf-8 -*-
class Solution:
def FindKthToTail(self, head, k):
# write code here
if head==None or k==0:
return None
pHead=head
pBehind=None
for i in range(k-1):
if pHead.next!=None:
pHead=pHead.next
else:return None
pBehind=head
while pHead.next!=None:
pBehind=pBehind.next
pHead=pHead.next
return pBehind
算法思想二:开辟空间,把链表转化为列表或数组,然后利用list的切片,找到倒数第k个值
# -*- coding:utf-8 -*-
class Solution:
def FindKthToTail(self, head, k):
# write code here
if head==None or k==0:
return None
l=[]
while head!=None:
l.append(head)
head=head.next
if k<1 or k>len(l):
return None
result=l[-k]
return result
举一反三:
问题:输入一个链表,反转链表后,输出链表的所有元素。
# -*- coding:utf-8 -*-
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
if pHead==None or pHead.next==None:
return pHead
result=None
while pHead!=None:
temp=pHead.next #保存下一个节点
pHead.next=result #当前节点放到结果的开头
result=pHead #当前节点的头
pHead=temp #head指向下一个节点
return result
问题:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
# write code here
if pHead1==None:
return pHead2
elif pHead2==None:
return pHead1
result=None
if pHead1.valelse:
result=pHead2
result.next=self.Merge(pHead1,pHead2.next)
return result
问题:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
算法思想:使用递归遍历两棵树
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def HasSubtree(self, pRoot1, pRoot2):
# write code here
result=False
if not pRoot1 or not pRoot2:
return result
return self.DoseTree1HaveTree2(pRoot1, pRoot2) or self.DoseTree1HaveTree2(pRoot1.left, pRoot2) or self.DoseTree1HaveTree2(pRoot1.right, pRoot2)
def DoseTree1HaveTree2(self,tree1, tree2):
if not tree2 :
return True
if not tree1 or tree1.val!=tree2.val:
return False
return self.DoseTree1HaveTree2(tree1.left,tree2.left) and self.DoseTree1HaveTree2(tree1.right,tree2.right)
问题:操作给定的二叉树,将其变换为源二叉树的镜像。
算法思想:前序遍历树的每个结点,如果遍历到的结点有子节点,就交换它的两个子节点,当交换完所有的非叶子结点的左右子结点后,就得到了树的镜像。(这里使用递归的思想)
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回镜像树的根节点
def Mirror(self, root):
# write code here
if not root:
return root
if (not root.left) and (not root.right):
return root
root.left,root.right=root.right,root.left
if root.left:
self.Mirror(root.left)
if root.right:
self.Mirror(root.right)
问题:
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
算法思想:前序遍历树的每个结点,如果遍历到的结点有子节点,就交换它的两个子节点,当交换完所有的非叶子结点的左右子结点后,就得到了树的镜像。(这里使用递归的思想)
# -*- coding:utf-8 -*-
class Solution:
# matrix类型为二维列表,需要返回列表
def printMatrix(self, matrix):
# write code here
rows=len(matrix)
cols=len(matrix[0])
result=[]
if rows==1 and cols==1:
result= [matrix[0][0]]
return result
for m in xrange((min(rows,cols)+1)//2): #走的圈数:1xN即一行,走一圈;Nx1即一列,走一圈;
[result.append(matrix[m][i]) for i in xrange(m,cols-m)] #从左向右
[result.append(matrix[j][cols-1-m]) for j in xrange(m,rows-m) if matrix[j][cols-1-m] not in result] #从上到下
[result.append(matrix[rows-1-m][k]) for k in xrange(cols-1-m,m-1,-1) if matrix[rows-1-m][k] not in result] #从右到左
[result.append(matrix[l][m]) for l in xrange(rows-1-m,m-1,-1) if matrix[l][m] not in result] #从下到上
return result
问题:定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
算法思想:借助于中间栈
往数据栈压入数据时,同时往辅助栈中压入最小数。(比较当前数据和最小值的大小,如果比最小值到,往辅助栈压入最小值,如果比最小值小,压入辅助栈,并且更新最值);出栈时,每次数据栈弹出数据,辅助栈也弹出数据,则辅助栈的栈顶总是最下值。
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.stack=[] #数据栈
self.min_stack=[] #辅助栈
def push(self, node):
# write code here
self.stack.append(node)
if not self.min_stack or node<=self.min_stack[-1]:
self.min_stack.append(node)
def pop(self):
# write code here
if self.stack[-1]==self.min_stack[-1]:
self.min_stack.pop()
self.stack.pop()
def top(self):
# write code here
return self.stack[-1]
def min(self):
# write code here
return self.min_stack[-1]
问题:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
算法思想:借用一个辅助的栈,遍历压栈顺序,先讲第一个放入栈中,这里是1,然后判断栈顶元素是不是出栈顺序的第一个元素,这里是4,很显然1≠4,所以我们继续压栈,直到相等以后开始出栈,出栈一个元素,则将出栈顺序向后移动一位,直到不相等,这样循环等压栈顺序遍历完成,如果辅助栈还不为空,说明弹出序列不是该栈的弹出顺序。
# -*- coding:utf-8 -*-
class Solution:
def IsPopOrder(self, pushV, popV):
# write code here
if not pushV or len(pushV)!=len(popV):
return False
stack=[]
for i in pushV:
stack.append(i)
while len(stack) and stack[-1]==popV[0]:
stack.pop()
popV.pop(0)
if len(stack):
return False
return True
问题:从上往下打印出二叉树的每个节点,同层节点从左至右打印。
算法思想:使用队列
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回从上到下每个节点值列表,例:[1,2,3]
def PrintFromTopToBottom(self, root):
# write code here
if not root:
return []
queue=[root]
result=[]
while len(queue):
node=queue.pop(0)
result.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
问题:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
算法思想:二叉搜索树的特点,左子树比根节点小,右子树比根节点大;后序遍历就是左–>右–>根的顺序。使用递归思想,首先找到左右子树,然后递归。
# -*- coding:utf-8 -*-
class Solution:
def VerifySquenceOfBST(self, sequence):
# write code here
if not sequence:
return False
if len(sequence)==1:
return True
root=sequence[-1]
leftLen=0
while sequence[leftLen]#左子树
leftLen+=1
rightLen=leftLen
for k in sequence[leftLen:len(sequence)-1]:
if kreturn False
left_tr=sequence[:leftLen]
right_tr=sequence[rightLen:len(sequence)-1]
leftIs = True
rightIs = True
if len(left_tr):
leftIs=self.VerifySquenceOfBST(left_tr)
if len(right_tr):
rightIs=self.VerifySquenceOfBST(right_tr)
return leftIs and rightIs