剑指offer-Python版答案

最近在看剑指offer,原书都是用C++实现的,考虑用Python实现一遍所有问题答案。由于牛客网有剑指offer的在线评测,所以本文所有代码都基于牛客网上的问题(可能会和原书题目描述不同)实现。

字符串

替换空格

题目描述:在线编程

请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

分析:

Python中直接使用字符串的replace函数即可。

代码:

1
2
3
4
5
# -*- coding:utf-8 -*-
class Solution:
# s 源字符串
def replaceSpace(self, s):
return s.replace(' ', '%20')

正则表达式匹配

题目描述:在线编程

请实现一个函数用来匹配包括.*的正则表达式。模式中的字符.表示任意一个字符,而*表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串”aaa”与模式”a.a”和”abaca”匹配,但是与”aa.a”和”ab*a”均不匹配

分析:

直接使用python中的正则表达式进行完全匹配即可解决此问题。

代码:

1
2
3
4
5
6
7
8
9
10
# -*- coding:utf-8 -*-
class Solution:
# s, pattern都是字符串
def match(self, s, pattern):
import re
result = re.findall('^' + pattern + '$', s)
if result:
return True
else:
return False

表示数值的字符串

题目描述:在线编程

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串”+100”,”5e2”,”-123”,”3.1416”和”-1E-16”都表示数值。 但是”12e”,”1a3.14”,”1.2.3”,”+-5”和”12e+4.3”都不是。

分析:

可以用float函数是否抛出ValueError异常来判断,或是直接写正则表达式。

代码:

1
2
3
4
5
6
7
8
9
10
# -*- coding:utf-8 -*-
class Solution:
# s字符串
def isNumeric(self, s):
try:
float(s)
except ValueError:
return False
else:
return True

数组

数组中只出现一次的数字

题目描述:在线编程

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

分析:

每次从列表中pop出一个值,如果这个值在列表中还存在,则直接从列表中remove掉这个值,如果不存在则加入结果列表中。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
# -*- coding:utf-8 -*-
class Solution:
# 返回[a,b] 其中ab是出现一次的两个数字
def FindNumsAppearOnce(self, array):
result = []
while array:
number = array.pop()
if number not in array:
result.append(number)
else:
array.remove(number)
return result

二维数组中的查找

题目描述:在线编程

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

分析1:

如果不考虑题目特点的话(每行每列都递增),直接迭代列表每一行,检测该值是否在每一行的列表即可。

代码1:

1
2
3
4
5
6
7
# -*- coding:utf-8 -*-
class Solution:
# array 二维列表
def Find(self, target, array):
for row in array:
if target in row:
return True

分析二:

由于题目特点,每行每列都递增,则可以每次比较最右上角的数字,如果相等则返回,输入的数大于右上角的数,则排除这一行,输入的数小于右上角的数,则排除这一列。

代码二:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# -*- coding:utf-8 -*-
class Solution:
# array 二维列表
def Find(self, target, array):
row = 0
col = len(array[0]) - 1
while row < len(array) and col >= 0:
if array[row][col] == target:
return True
elif array[row][col] < target:
row += 1
else:
col -= 1
return False

栈和队列

用两个栈实现队列

题目描述:在线编程

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

分析:

两个栈,一个作为队首,一个作为队尾,队列Push操作就是向队尾栈添加元素,队列Pop操作,需要先判断队首栈是否为空,如不空,则队首栈栈顶元素出栈,如为空,则将队尾栈所有元素依次pop出来,并push到队首栈,然后再队首栈顶元素出栈。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.front = []
self.rear = []
def push(self, node):
self.rear.append(node)
def pop(self):
if not self.front:
while self.rear:
self.front.append(self.rear.pop())
return self.front.pop()

包含min函数的栈

题目描述:在线编程

定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。

分析:

借助一个辅助栈,存储当前栈中最小元值组成的栈,入栈时小于等于辅助栈顶值时则同时也入辅助栈,出栈时,如等于辅助栈栈顶值,则辅助栈同步出栈这个值。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.stack = []
self.min_stack = []
def push(self, node):
if not self.min_stack or node <= self.min_stack[-1]:
self.min_stack.append(node)
self.stack.append(node)
def pop(self):
if self.top() == self.min_stack[-1]:
self.min_stack.pop()
self.stack.pop()
def top(self):
return self.stack[-1]
def min(self):
return self.min_stack[-1]

栈的压入、弹出序列

题目描述:在线编程

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

分析:

借助一个辅助栈实际模拟入栈出栈,最后看辅助栈是否为空即可。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
# -*- coding:utf-8 -*-
class Solution:
def IsPopOrder(self, pushV, popV):
stack = []
index = 0
for v in pushV:
stack.append(v)
while stack and stack[-1] == popV[index]:
stack.pop()
index += 1
return len(stack) == 0

递归和循环

斐波那契数列

题目描述:在线编程

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39

分析:

在数学上,斐波那契数列是用递归的方法定义的:
F(0)= 0 (n = 0)
F(1)= 1 (n = 1)
F(n)= F(n-1)+ F(n - 2)(n >= 2)
如果程序中采用递归的方法话,那必定会超时的,因此要用循环的方法。

代码:

1
2
3
4
5
6
7
# -*- coding:utf-8 -*-
class Solution:
def Fibonacci(self, n):
prev, next = 0, 1
for _ in range(n):
prev, next = next, prev+next
return prev

跳台阶

题目描述:在线编程

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

分析:

F(0)= 0
F(1)= 1
F(2)= 2
F(n)= F(n-1)+ F(n-2)(n > 2)

代码:

1
2
3
4
5
6
7
8
9
# -*- coding:utf-8 -*-
class Solution:
def jumpFloor(self, number):
if number <= 2:
return number
prev, curr = 1, 2
for _ in range(3, number+1):
prev, curr = curr, prev+curr
return curr

变态跳台阶

题目描述:在线编程

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

分析:

F(0)= 0
F(1)= 1
F(2)= 2
F(n)= F(n-1)+ F(n-2)+ … + F(2)+ F(1)+ 1 = 2 **(n-1)

代码:

1
2
3
4
# -*- coding:utf-8 -*-
class Solution:
def jumpFloorII(self, number):
return 2**(number-1)

矩形覆盖

题目描述:在线编程

我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

分析:

F(0)= 0
F(1)= 1
F(2)= 2
F(n)= F(n-1)+ F(n-2)(n > 2)

代码:

1
2
3
4
5
6
7
8
9
# -*- coding:utf-8 -*-
class Solution:
def rectCover(self, number):
if number <= 2:
return number
prev, curr = 1, 2
for _ in range(3, number+1):
prev, curr = curr, prev+curr
return curr

大师兄 wechat
欢迎关注我的微信公众号:Python大师兄