1、矩阵覆盖
我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2n的大矩形,总共有多少种方法?比如n=3时,23的矩形块有3种覆盖方法:
解题思路:(斐波那契数列)
n=1,f(1)=1;
n=2,f(2)=2;
n=3,f(3)=3;
n=4,f(4)=5;
n=5,f(5)=8;
…
n=n,f(n)=f(n-1)+f(n-2),每一个都是在上一个的里面进行变形的。
拓展:
(1)1 X3方块 覆 盖3Xn区域:f(n) = f(n-1) + f(n - 3), (n > 3)
(2) 1 X4 方块 覆 盖4Xn区域:f(n) = f(n-1) + f(n - 4),(n > 4)
更一般的结论,如果用1m的方块覆盖mn区域,递推关系式为f(n) = f(n-1) + f(n-m),(n > m)。
# -*- coding:utf-8 -*-
class Solution:
def rectCover(self, number):
# write code here
if number<1:
return 0
elif number==1:
return 1
elif number==2:
return 2
else:
s = [] * number
s.append(1) # s[0]
s.append(2) # s[1]
for i in range(2, number):
s.append(s[i - 2] + s[i - 1])
return s[number - 1]
jz=Solution()
print(jz.rectCover(5))
2、和为S的两个数字
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
# -*- coding:utf-8 -*-
class Solution:
def FindNumbersWithSum(self, array, tsum):
# write code here
# 因为是递增数组,所以最靠两边的一对就是积最小的
l = []
for x in array:
l.append(tsum-x)
for y in l:
if y in array: # 满足条件就直接return结果了
return [tsum-y,y] # 结束循环
return []
AR=[1,2,3,4,5,8]
cjs=Solution()
print(cjs.FindNumbersWithSum(AR,7))
3、和为S的连续正数序列
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
解题思路:
最后举一个例子,例如输入15,由于1+2+3+4+5=4+5+6=7+8=15;所以打印出三个连续序列1 ~ 5, 4 ~ 6, 7 ~ 8。
class Solution:
def FindContinuousSequence(self, tsum):
low, high = 1, 2
res = []
while low <= tsum // 2:
if sum(range(low, high + 1)) == tsum:
res.append(list(range(low, high + 1)))
low += 1
elif sum(range(low, high + 1)) < tsum:
high += 1
else:
low += 1
return res
s=Solution()
print(s.FindContinuousSequence(15))
4、链表
python中的列表:append数据就相当于链表的增加和删减。(数组是固定长度的,链表和列表时可变化的。)
4.1 构建链表并打印
class ListNode:
'''
链表的结构
x:值value
next:指向下一个的指针
'''
def __init__(self, x):
self.val = x
self.next = None
def prinListNode(node):
# 打印链表
while node:
print(node.val)
node=node.next
if __name__ == '__main__':
# 1 --> 2 --> 3 -->none
l1=ListNode(1)
l2 = ListNode(2)
l3 = ListNode(3)
l1.next=l2
l2.next=l3
l3.next=None
ListNode.prinListNode(l1)
4.2从尾到头打印链表
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
解题思路:
创造一个和原链表等长的空列表,然后取一个放进一个,再打印。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# ListNode:3-->2-->1-->none
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
# write code here
ret=[]
pTemp=listNode
while pTemp:
ret.insert(0,pTemp.val) # 每次都在列表的头添加
pTemp=pTemp.next
return ret
4.3 打印链表中倒数第K个节点
输入一个链表,输出该链表中倒数第k个结点。
解题思路:
定义两个变量,这两个变量间隔大小为k,一起向后移动,知道一个变量到尾部,那么另一个变量对应的位置就是倒数第K个节点度的位置。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindKthToTail(self, head, k):
# write code here
# 边界条件k和链表的大小比较
firstpoint=head
secondpoint=head
for i in range(k):
if firstpoint==None:
return None
firstpoint=firstpoint.next
pass
while firstpoint != None:
firstpoint=firstpoint.next
secondpoint=secondpoint.next
return secondpoint
4.4 反转链表
输入一个链表,反转链表后,输出新链表的表头。
解题思路:
将现有的头换成尾,尾部的next为空
将从第二个node开始,循环将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
if not pHead or not pHead.next:
return pHead
last = None
while pHead:
tmp = pHead.next
pHead.next = last
last = pHead
pHead = tmp
return last
4.5合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2): # pHead1相当于一个ListNode,包含val和next两部分
# write code here
if pHead1 ==None:
return pHead2
if pHead2 == None:
return pHead1
# 确定开始的节点
newHead = pHead1 if pHead1.val < pHead2.val else pHead2
ptemp1=pHead1
ptemp2=pHead2
if newHead == ptemp1:
ptemp1= ptemp1.next
else:
ptemp2 = pHead2.next
prepoint = newHead
while ptemp1 and ptemp2: # 有一个为空就停止
if ptemp1.val < ptemp2.val:
prepoint.next = ptemp1
prepoint = ptemp1
ptemp1 = ptemp1.next
else:
prepoint.next = ptemp2
prepoint = ptemp2
ptemp2 = ptemp2.next
if ptemp1 == None:
prepoint.next = ptemp2
else:
prepoint.next = ptemp1
return newHead # 表头代表整个链表
4.6 复杂链表的复制
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点,random指针可能会指向自己;),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空):
方法1:
# -*- coding:utf-8 -*-
# class RandomListNode:
# def __init__(self, x):
# self.label = x # value
# self.next = None
# self.random = None
# 方法1
import copy
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
ret = copy.deepcopy(pHead)
return ret
方法2:
a中由几个node就在每个node后面加一个相同的nodeA:A.next.random=a.random.next
# -*- coding:utf-8 -*-
# class RandomListNode:
# def __init__(self, x):
# self.label = x # value
# self.next = None
# self.random = None
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
if pHead== None:
return None
# 1、添加一样的value节点
ptemp = pHead
while ptemp:
node = RandomListNode(ptemp.label) # 创建相同节点
node.next = ptemp.next
ptemp.next = node
ptemp=ptemp.next.next
# 2、实现新建node的random指针的指向
ptemp = pHead
while ptemp:
if ptemp.random: # random没有指向的时候
ptemp.next.random = ptemp.random.next
ptemp = ptemp.next.next
# 3、一分为二
ptemp = pHead
newHead = pHead.next
pnew = pHead.next
while ptemp:
ptemp.next = ptemp.next.next
if pnew.next:
pnew.next = pnew.next.next
pnew = pnew.next
ptemp = ptemp.next
return newHead
测试:
# -*- coding:utf-8 -*-
class RandomListNode:
def __init__(self, x):
self.label = x # value
self.next = None
self.random = None
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
if pHead== None:
return None
# 1、添加一样的value节点
ptemp = pHead
while ptemp:
node = RandomListNode(ptemp.label) # 创建相同节点
node.next = ptemp.next
ptemp.next = node
ptemp=ptemp.next.next
# 2、实现新建node的random指针的指向
ptemp = pHead
while ptemp:
if ptemp.random: # random没有指向的时候
ptemp.next.random = ptemp.random.next
ptemp = ptemp.next.next
# 3、一分为二
ptemp = pHead
newHead = pHead.next
pnew = pHead.next
while ptemp:
ptemp.next = ptemp.next.next
if pnew.next:
pnew.next = pnew.next.next
pnew = pnew.next
ptemp = ptemp.next
return newHead
if __name__ == '__main__':
n1 = RandomListNode(1)
n2 = RandomListNode(2)
n3 = RandomListNode(3)
n1.next = n2
n2.next = n3
n1.random = n2
n2.random = n2
n3.random = n1
s=Solution()
newHead = s.Clone(n1) #n1就表示pHead,表示整个链表
temp = newHead
print(temp)
while temp:
print(temp.label)
temp = temp.next
4.6 两个链表的第一个公共结点
输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindFirstCommonNode(self, head1, head2):
# write code here
list1 = []
node1 = head1
node2 = head2
while node1:
list1.append(node1.val)
node1 = node1.next
while node2:
if node2.val in list1:
return node2
else:
node2 = node2.next
4.6 链表中环的入口节点
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
if not pHead:
return None
plist = []
while True:
plist.append(pHead.val)
pHead = pHead.next
if not pHead:
return None
if pHead.val in plist:
return pHead
4.7 删除链表中重复的节点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
解题思路:
空链表可以没有头结点,不能没有头指针。如果有头结点的话,头指针必然指向头结点。头结点是用来存储诸如链表长度之类的信息的,可有可无,而头指针是指向这个链表的地址的关键指针,如果没有它,这个链表就找不到,相当于没创建一样。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def deleteDuplication(self, pHead):
# 1、将链表中的节点val放入列表中
temp = []
head = pHead
while head:
temp.append(head.val)
head = head.next
# 2、创建一个空链表,头指针为head
res = ListNode(None)
head = res
# 3、填充不重复的节点信息
for i in temp:
if temp.count(i) == 1:
head.next = ListNode(i)
head = head.next
return res.next