根据我的大厂面试经验,剑指offer的题一定都要熟练掌握,面试时极有可能让我们手撕部分题的代码,当然这是最简单的情况,像BAT这类的大厂大部分时候让我们手撕 动态规划 题。总之,剑指offer的题目算法思路我们一定要会!!!
1、二维数组中的查找
题目描述:
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
示例1
题解python代码:
# -*- coding:utf-8 -*-
class Solution:
# array 二维列表
def Find(self, target, array):
# write code here
if not array[0]: return False
l,r,n = 0,len(array)-1,len(array)
for A in array:
if self.binary(target, A, l, r):
return True
return False
def binary(self, t, array, l, r):
while l<=r:
m = (l+r)//2
if array[m]<t: l = m+1
elif array[m]==t: return True
else: r = m-1
return False
2、替换空格
题目描述:
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
示例1
题解python代码:
注:也可以将s拆成列表,然后在中间插入 “%20”
class Solution:
def replaceSpace(self , s ):
# write code here
return s.replace(" ","%20")
3、从尾到头打印链表
题目描述:
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
示例1
题解python代码:
# -*- 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
stack = []
while listNode:
stack.append(listNode.val)
listNode = listNode.next
return stack[::-1]
4、重建二叉树
题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
示例1
题解python代码:
# -*- 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):
if len(pre)==0:
return
# write code here
root = TreeNode(pre[0])
root_index = tin.index(pre[0])
root.left = self.reConstructBinaryTree(pre[1:root_index+1], tin[:root_index])
root.right = self.reConstructBinaryTree(pre[root_index+1:], tin[root_index+1:])
return root
5、用两个栈实现队列
题目描述:
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
题解python代码:
注:我在题目的基础加入了 peek(查看队头元素),empty(是否为空),init(初始化),三种方法。
class MyQueue(object):
def __init__(self):
self.stack1 = []
self.stack2 = []
def push(self, x):
self.stack1.append(x)
def pop(self):
if not self.stack2:
while self.stack1:
self.stack2.append(self.stack1.pop())
return self.stack2.pop()
def peek(self):
if not self.stack2:
while self.stack1:
self.stack2.append(self.stack1.pop())
return self.stack2[-1]
def empty(self):
return not self.stack1 and not self.stack2
6、旋转数组的最小数字
题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
示例1
题解python代码:
# -*- coding:utf-8 -*-
class Solution:
def minNumberInRotateArray(self, rotateArray):
# 可以使用min()函数, 但是在不适用min函数的情况下,思路应该是二分查找
# 下面使用 递归实现2分查找,其中递归的时候必须使用return!!! 不然会返回none
# write code here
start = 0
end = len(rotateArray) - 1
mid = int((start + end) / 2)
if len(rotateArray) == 2:
if rotateArray[0]>rotateArray[1]:
return rotateArray[1]
else:
return rotateArray[0]
elif rotateArray[mid] > rotateArray[end]:
return self.minNumberInRotateArray(rotateArray[mid:end + 1])
elif rotateArray[mid] < rotateArray[start]:
return self.minNumberInRotateArray(rotateArray[start:mid + 1])
7、斐波那契数列
题目描述:
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。
n≤39
示例1
题解python代码:
注:递归会超时
# -*- coding:utf-8 -*-
class Solution:
def Fibonacci(self, n):
if n<2: return n
# write code here
A = [0]*(n+1)
A[1] = 1
for i in range(2, n+1):
A[i] = A[i-1]+A[i-2]
return A[-1]
8、跳台阶
题目描述:
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
示例1
题解python代码:
注:递归会超时
# -*- coding:utf-8 -*-
class Solution:
def jumpFloor(self, number):
# write code here
# if number<3:
# return number
# return self.jumpFloor(number-1)+self.jumpFloor(number-2)
if number <= 2:
return number
a, b = 1, 2
for i in range(3,number+1):
a, b = b, a + b
print(b)
return b
9、跳台阶扩展问题
题目描述:
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
示例1
题解python代码:
注:找规律的题目
# -*- coding:utf-8 -*-
class Solution:
def jumpFloorII(self, number):
# write code here
return 2**(number-1)
10、矩形覆盖
题目描述:
我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
比如n=3时,2*3的矩形块有3种覆盖方法:
示例1
题解python代码:
# -*- coding:utf-8 -*-
class Solution:
def rectCover(self, number):
# write code here
if number<4: return number
A = [i for i in range(number+1)]
for i in range(4, number+1):
A[i] = A[i-1]+A[i-2]
return A[-1]
11、二进制中1的个数
题目描述:
输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。
示例1
题解python代码:
注:python32位二进制负数补码的表示https://blog.csdn.net/weixin_44414948/article/details/114809621
# -*- coding:utf-8 -*-
class Solution:
def NumberOf1(self, n):
# write code here
if n<0: n = n&0xffffffff
count = 0
temp = 0x00000001
for i in range(64):
if n&temp: count += 1
temp = temp<<1
return count
12、数值的整数次方
题目描述:
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
保证base和exponent不同时为0
示例1
题解python代码:
注:二分法中的倍增法
# -*- coding:utf-8 -*-
class Solution:
def Power(self, base, exponent):
# write code here
if base==0: return 0
if exponent==0: return 1
flag = 1
if exponent<0:
exponent = -exponent
flag = -1
# exponent,flag = -exponent,-1 if exponent<0 else exponent,1
temp = 1
ans = base
while exponent>1:
if exponent%2==1:
temp *= base
exponent -= 1
ans *= ans
exponent /= 2
return ans*temp if flag==1 else 1/(ans*temp)
13、调整数组顺序使奇数位于偶数前面
题目描述:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
示例1
题解python代码:
注:两个辅助栈
class Solution:
def reOrderArray(self , array ):
# write code here
A,B = [],[]
for a in array:
if a%2==1: A.append(a)
else: B.append(a)
return A+B
14、链表中倒数第k个结点
题目描述:
输入一个链表,输出该链表中倒数第k个结点。
示例1
题解python代码:
注:快慢指针法
class Solution:
def FindKthToTail(self , pHead , k ):
# write code here
if not pHead: return None
fast,slow = pHead, pHead
while fast and k>0: # fast、k同时往下一个滑动
fast = fast.next
k -= 1
if k>0: return None # fast滑到尾部时k仍然大于0,则k大于整个链表的长度
while fast: # 快慢指针同时往下滑动(两者相差k个长度),fast滑到尾部时,slow即为倒数第k个节点
fast = fast.next
slow = slow.next
return slow
15、反转链表
题目描述:
输入一个链表,反转链表后,输出新链表的表头。
示例1
题解python代码:
方法一、辅助栈法
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
# 1、辅助栈
stack = []
ans = temp = ListNode(0)
while pHead:
stack.append(pHead.val)
pHead = pHead.next
while stack:
temp.next = ListNode(stack.pop())
temp = temp.next
return ans.next
方法二、指针倒转法
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
# 2、指针倒转
if not pHead or not pHead.next: return pHead
last = None
while pHead:
temp = pHead.next # 保存next信息
pHead.next = last # 将pHead的next指针指向last
last = pHead # 将last变为pHead,准备变为pHead.next的下一个
pHead = temp # 更新pHead为其原本的下一个节点
return last
16、合并两个排序的链表
题目描述:
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
示例1
题解python代码:
方法一、辅助栈法
# -*- 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
# 1、辅助栈
stack = []
while pHead1 or pHead2:
if pHead1:
stack.append(pHead1.val)
pHead1 = pHead1.next
if pHead2:
stack.append(pHead2.val)
pHead2 = pHead2.next
stack.sort()
ans = current = ListNode(0)
for s in stack:
current.next = ListNode(s)
current = current.next
return ans.next
方法二、直接添加
# -*- 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
# 2、直接添加
ans = temp = ListNode(0)
while pHead1 and pHead2:
if pHead1.val<pHead2.val:
temp.next = pHead1
pHead1 = pHead1.next
else:
temp.next = pHead2
pHead2 = pHead2.next
temp = temp.next
if not pHead1:
temp.next = pHead2
if not pHead2:
temp.next = pHead1
return ans.next