1、在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
# -*- coding:utf-8 -*-
class Solution:
# array 二维列表
def Find(self, target, array):
// 行数
n=len(array)
// 列数
m=len(array[0])
i=n-1
j=0
while i>=0 and j<=m-1:
if array[i][j]<target:
j+=1
elif array[i][j]>target:
i-=1
else:
return True
return False
2、请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
class Solution:
# s 源字符串
def replaceSpace(self, s):
l=len(s)
new=[]
for i in range(l):
if s[i]==" ":
new.append("%20")
else:
new.append(s[i])
return "".join(new)
注意!
3、输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。(不熟练)
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
if listNode==None:
return []
else:
return self.printListFromTailToHead(listNode.next)+[listNode.val]
4、输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
class Solution:
def reConstructBinaryTree(self, pre, tin):
if not pre or not tin:
return None
root = TreeNode(pre.pop(0))
index = tin.index(root.val)
root.left = self.reConstructBinaryTree(pre, tin[:index])
root.right = self.reConstructBinaryTree(pre, tin[index + 1:])
return root
pop(0)返回pop(0)的值,并且删除pre里面的pop(0)
按照中序(左根右),将数分为左右,继续回溯。
注意:if not pre or not tin 不能写成pre==None or tinNone
5、用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。(不熟练,注意注意超级难!!!)
1.队列:先进先出(First In First Out)FIFO
2.栈:先进后出(First In Last Out )FILO
1,整体思路是元素先依次进入栈1,再从栈1依次弹出到栈2,然后弹出栈2顶部的元素,整个过程就是一个队列的先进先出
2,但是在交换元素的时候需要判断两个栈的元素情况:
“进队列时”,直接进A栈
“出队列时”,将栈A的元素全部弹到栈B中,保持在“出队列状态”。
所以要做的判断是,进时,栈B是否为空,不为空,则直接弹出,空时,将栈A元素全部弹到栈B中,直到栈A为空。
class Solution:
def __init__(self):
self.stockA=[]
self.stockB=[]
def push(self, node):
self.stockA.append(node)
def pop(self):
if self.stockB==[]:
if self.stockA==[]:
return None
else:
while self.stockA:
self.stockB.append(self.stockA.pop())
return self.stockB.pop()
6、把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。(没做出来!!))
法一:
class Solution:
def minNumberInRotateArray(self, rotateArray):
l=len(rotateArray)
for i in range(l-1):
if rotateArray[i]<=rotateArray[i+1]:
continue
else:
return rotateArray[i+1]
法二:(二分法,比较中间和右边,如果中间比右边小,则右边替换为中间;中间比右边大,则把左边置为中间值,其他相等的情况,r–,最后输出左边的值即是最小)
class Solution:
def minNumberInRotateArray(self, rotateArray):
l=len(rotateArray)
if l==0:
return 0
if l==1:
return rotateArray[0]
l,r=0,l-1
while l<=r:
m=(l+r)/2
if rotateArray[m]>rotateArray[r]:
l=m+1
elif rotateArray[m]<rotateArray[r]:
r=m
else:
r-=1
return rotateArray[l]
7、大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。(不熟练!)
n<=39
(回溯法不行,时间复杂度太高,不能通过!!)
斐波那契数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
class Solution:
def Fibonacci(self, n):
if n<2:
return n
else:
a=0
b=1
##从2开始,执行n-2次,输出b
for i in range(2,n+1):
a,b=b,a+b
return b
8、一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
跟斐波那契数列差不多,从后往前推,每次都是前一个的跳法数+前前一个的跳法数
青蛙每一次跳跃只有两种选择:一是再跳1级阶梯到达第n级阶梯,此时小青蛙处于第n-1级阶梯;或者再跳2级阶梯到达第n级阶梯,此时小青蛙处于n-2级阶梯
于是,n级阶梯的跳法总是依赖于前n-1级阶梯的跳法总数f(n-1)和前n-2级阶梯的跳法总数f(n-2).因为只有两种可能性,所以,f(n)=f(n-1)+f(n-2);
递推公式f(n)=f(n-1)+f(n-2):很熟悉,就是斐波那契数列求和
但是注意 和斐波那契数列的起始值不一样 f(2)=2,而不是1 这是由于本题的特性确定的
class Solution:
def jumpFloor(self, number):
if number<=2:
return number
else:
fib1=1
fib2=2
for i in range(3,number+1):
fib1,fib2=fib2,fib1+fib2
return fib2
9、一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
[分析】 每个台阶可以看作一块木板,让青蛙跳上去,n个台阶就有n块木板,最后一块木板是青蛙到达的位子, 必须存在,其他 (n-1) 块木板可以任意选择是否存在,则每个木板有存在和不存在两种选择,(n-1) 块木板 就有 [2^(n-1)] 种跳法,可以直接得到结果。
class Solution:
def jumpFloorII(self, number):
return 2**(number-1)
10、我们可以用2x1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2x1的小矩形无重叠地覆盖一个2xn的大矩形,总共有多少种方法?
还是一样的斐波那契数列
解析看这个:https://blog.youkuaiyun.com/fjswcjswzy/article/details/107978585
class Solution:
def rectCover(self, number):
if number<=2:
return number
else:
a=1
b=2
for i in range(3,number+1):
a,b=b,a+b
return b
11、输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
由于通常整数大小都是32位,所以按位与,和一相同,则计数
是右移,把最后一位和1与,每次都右移
class Solution:
def NumberOf1(self, n):
cnt = 0
for i in range(32):
cnt += (n >> i) & 1
return cnt
12、给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
注意!exponent可能为正数或者负数,注意区分情况
注意base=0且exponent小于0的情况 抛出异常
class Solution:
def Power(self, base, exponent):
if exponent==0:
return 1
if base==0 && exponent<0:
throw exception
sum=1
base=base**(abs(exponent)/exponent)
for i in range(abs(exponent)):
sum=base*sum
return sum
13、输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
同冒泡排序法 固定后面的数字 从前向后遍历 换顺序(时间复杂度高 比较慢 超过0.13%个人)
class Solution:
def reOrderArray(self, array):
l=len(array)
##冒泡排序的想法,如果偶数在奇数前面,两两交换,把最大的偶数冒泡到最后面,注意!!j从前往后遍历这样固定的是后面的数字。
for i in range(0,l,1):
for j in range(0,l-1-i,1):// 这里注意一定是l-i-i 不然会数组越界 因为下面是j+1
if array[j]%2==0 and array[j+1]%2==1:
array[j],array[j+1]=array[j+1],array[j]
return array
同上 只不过固定前面的奇数 从后向前遍历:稍微快点 超过了0.25%个人
class Solution:
def reOrderArray(self, array):
l=len(array)
##冒泡排序的想法,如果偶数在奇数前面,两两交换,把最大的偶数冒泡到最后面,注意!!j从后往前遍历这样固定前面的数字。
for i in range(l):
for j in range(l-1,i,-1):
if array[j-1]%2==0 and array[j]%2==1:
array[j-1],array[j]=array[j],array[j-1]
return array
还有一种 新建2个数组 分别存放奇数和偶数 时间 复杂度击败了 26.32% 空间复杂度击败了 46%
class Solution:
def reOrderArray(self, array):
l=len(array)
a=[]
b=[]
for i in range(l):
if array[i]%2==1:
a.append(array[i])
else:
b.append(array[i])
return a+b
14、输入一个链表,输出该链表中倒数第k个结点。
快慢指针
class Solution:
def FindKthToTail(self, head, k):
# 用快慢指针
kuai=man=head
for i in range(k):
##若指针长度比k小,则返回none
if kuai==None:
return None
else:
kuai=kuai.next
#当快指针从k,走到终点,即走过的距离是n-k;所以慢指针走过的距离是n-k,距离终点k
while kuai!=None:
kuai=kuai.next
man=man.next
return man
15、输入一个链表,反转链表后,输出新链表的表头。(不熟练!!)
pHead始终指向要反转的结点
new指向反转后的首结点
每反转一个结点,把pHead结点的下一个结点指向new, new指向pHead成为反转后首结点, 再把pHead向前移动一个结点直至None结束
class Solution:
def ReverseList(self, pHead):
##若链表为空或者长度为1,输出当前头结点
if not pHead or not pHead.next:
return pHead
else:
##从1-2-3-4-5变成,2指向1,5指向4,再返回new
new=None
while pHead:
temp=pHead.next
pHead.next=new
new=pHead
##phead向前移动
pHead=temp
return new
16、输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。(不熟练!!)
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
##创建一个新链表,用PHead记录头结点位置,方便之后返回整个链表
temp=ListNode(0)
pHead=temp
while pHead1 and pHead2:
if pHead1.val>pHead2.val:
temp.next=pHead2
pHead2=pHead2.next
else:
temp.next=pHead1
pHead1=pHead1.next
temp=temp.next
if pHead1==None:
temp.next=pHead2
else:
temp.next=pHead1
return pHead.next
17、输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)(太难了 要多看看,一点都想不到)
太难了!!!!
class Solution:
def HasSubtree(self, pRoot1, pRoot2):
result=False
if pRoot1 and pRoot2:
if pRoot1.val==pRoot2.val:
result=self.isequal(pRoot1,pRoot2)
if not result:
result=self.HasSubtree(pRoot1.left,pRoot2)
if not result:
result=self.HasSubtree(pRoot1.right,pRoot2)
return result
def isequal(self,pRoot1,pRoot2):
if pRoot2==None:
return True
if pRoot1==None:
return False
if pRoot1.val!=pRoot2.val:
return False
return self.isequal(pRoot1.left,pRoot2.left) and self.isequal(pRoot1.right,pRoot2.right)
18、操作给定的二叉树,将其变换为源二叉树的镜像。(不熟练!)
class Solution:
# 返回镜像树的根节点
def Mirror(self, root):
if not root:
return root
else:
root.left,root.right=root.right,root.left
self.Mirror(root.left)
self.Mirror(root.right)
return root
19、
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 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.(边界条件需要细想)
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if len(matrix)==0:
return []
res=[]
left,right,top,bottom=0,len(matrix[0])-1,0,len(matrix)-1
while(True):
for i in range(left,right+1):
res.append(matrix[top][i])
top=top+1
if top>bottom:
break
for i in range(top,bottom+1):
res.append(matrix[i][right])
right=right-1
if right<left:
break
for i in range(right,left-1,-1):
res.append(matrix[bottom][i])
bottom=bottom-1
if bottom<top:
break
for i in range(bottom,top-1,-1):
res.append(matrix[i][left])
left=left+1
if left>right:
break
return res
解析过程:
class Solution {
public int[] spiralOrder(int[][] matrix) {
//base case 如果返回空,最后一个测试用例不过(不要问我怎么知道的)
if(matrix.length == 0) return new int[0];
//初始化:左、右、上、下、以及指针计数器。
int left = 0, right = matrix[0].length - 1, top = 0, bottom = matrix.length - 1,count = 0;
//初始化结果数组
int[] res = new int[(right + 1) * (bottom + 1)];
while(true){
//第一次循环:从顶部左侧---->顶部右侧 把结果放进res中
for(int i = left;i <= right; i++){
res[count++] = matrix[top][i];
}
//此时,顶部的数已经存进数组,需要缩小top空间,并且 top > bottom 说明到达了底部,直接返回;
if(++top > bottom)break;
//第二次循环:从右侧顶部-------->右侧底部 把结果放进res中
for(int i = top; i <= bottom; i++){
res[count++] = matrix[i][right];
}
//此时,右侧的数已经添加进数组,所以要缩小右侧空间 并且 --right < left 说明右侧缩小到了左侧,直接返回
if(--right < left){
break;
}
//第三次循环:从底部右侧------>底部左侧:把结果放进res中
for(int i = right; i >= left; i--){
res[count++] = matrix[bottom][i];
}
//此时,底部的数已经添加到数组中,所以要缩小底部的空间,并且 --bottom < top 说明底部已经缩小到了顶部,直接返回
if(--bottom < top)break;
//第四次循环:从左侧底部------>左侧顶部 把结果放进res中
for(int i = bottom; i >= top; i--){
res[count++] = matrix[i][left];
}
//此时,左侧的数已经添加到了数组中,所以要缩小左侧空间 并且 ++left > right 说明左侧缩小到了右侧 直接返回
if(++left > right)break;
}
return res;
20、定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。(没做出来 难难难)
思路:利用一个辅助栈来存放最小值
栈 3,4,2,5,1
辅助栈 3,3,2,2,1
每入栈一次,就与辅助栈顶比较大小,如果小就入栈,如果大就入栈当前的辅助栈顶
当出栈时,辅助栈也要出栈
这种做法可以保证辅助栈顶一定都当前栈的最小值
class MinStack:
def __init__(self):
self.stack1=[]
// math.inf是正无穷大
self.stack2=[math.inf]
def push(self, node):
self.stack1.append(node)
self.stack2.append(min(node, self.stack2[-1]))
def pop(self):
self.stack2.pop()
self.stack1.pop()
def top(self) -> int:
return self.stack1[-1]
def min(self):
return self.stack2[-1]