剑指offer(牛客网)day4

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值