蓝桥杯Python链表部分题目总结

蓝桥杯Python题目整理—链表

以下题目选自

  • 蓝桥云课:https://www.lanqiao.cn/courses/5456

  • LeetCode:https://leetcode-cn.com/problemset/all/

    • LeetCode83:删除排序链表中的重复元素
    • 剑指offer22:删除链表的重复项
    • 剑指offer18:删除链表的结点
    • LeetCode86:分隔链表
    • 面试题02.05:链表求和
    • LeetCode234:回文链表

1. 实现链表类

挑战介绍

实现链表的插入,增加,查找,删除,查看长度和打印的方法。链表的介绍如下:

  • 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
  • 链表中每一个元素称为结点,链表由一系列结点组成,结点可以在运行时动态生成。
  • 链表的每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

挑战内容

本次挑战中,你需要在 linkedlist.py 文件中补充类 Node 和类 LinkedList 的空缺部分。

  • Node 类是定义的结点类。
  • Node 中的 __init__ 方法用于初始化结点,结点包含数据元素 data 和指向下一个结点地址的指针 next_node
  • Node 中的 __str__ 方法用于返回当使用 print 输出对象时打印的信息,它需要返回结点的数据元素。
  • LinkedList 类是定义的链表类。
  • LinkedList 中的 __init__ 方法用于初始化链表,参数 head 为链表头的指针。
  • LinkedList 中的 __len__ 方法用于返回链表的结点个数,它需要返回一个数字。
  • LinkedList 中的 insert_to_front 方法用于在链表前面插入结点,参数 data 用于指定结点的数据元素,它需要返回插入的结点。如果 dataNone 则返回 None
  • LinkedList 中的 append 方法用于在链表后面增加结点,参数 data 用于指定结点的数据元素,它需要返回增加的结点。如果 dataNone 则返回 None
  • LinkedList 中的 find 方法用于查找链表中包含指定数据元素的结点,参数 data 用于指定结点的数据元素,它需要返回找到的结点。如果无法找到数据,则返回 None
  • LinkedList 中的 delete 方法用于删除链表中包含指定数据元素的结点,参数 data 用于指定结点的数据元素,它不需要返回任何值。如果链表没有结点,或者指定元素不在链表中,则不进行删除操作。
  • LinkedList 中的 print_list 方法用于打印链表所有结点的数据元素。它需要使用 print 函数从链表头至链表尾依次打印出结点的数据元素。
  • LinkedList 中的 get_all_data 方法用于将链表转化为数组,数组的元素为链表结点的数据元素,它需要返回一个数组。

挑战要求

  • 代码必须写入 linkedlist.py 文件中,且不能修改示例代码中出现的类名和函数名。
  • 请自行在环境主目录下新建 linkedlist.py 文件,并复制示例代码到文件中完成补充。补充完整后点击「提交检测」,系统将会给出判定结果。

思路

经典模板,无需顺利思路

解决方案

class Node(object):

    def __init__(self, data, next=None):
        ### 补充代码 ###
        self.next = next
        self.data = data

    def __str__(self):
        ### 补充代码 ###
        return self.data


class LinkedList(object):

    def __init__(self, head=None):
        ### 补充代码 ###
        self.head = head

    def __len__(self):
        ### 补充代码 ###
        cur = self.head
        count = 0
        while cur is not None:
            count += 1
            cur = cur.next
        return count

    def insert_to_front(self, data):
        ### 补充代码 ###
        if data is None:
            return None
        node = Node(data,self.head)
        self.head = node
        return node

    def append(self, data):
        ### 补充代码 ###
        if data is None:
            return None
        node = Node(data)
        if self.head is None:
            self.head = node
            return node
        cur = self.head
        while cur.next is not None:
            cur = cur.next
        cur.next = node
        return node

    def find(self, data):
        ### 补充代码 ###
        if data is None:
            return None
        cur = self.head
        while cur is not None:
            if cur.data == data:
                return cur
            cur = cur.next
        return None

    def delete(self, data):
        ### 补充代码 ###
        if data is None:
            return
        if self.head is None:
            return
        if self.head.data == data:
            self.head = self.head.next
            return
        pre = self.head
        cur = self.head.next
        while cur is not None:
            if cur.data == data:
                pre.next = cur.next
                return
            pre = cur
            cur = cur.next

    def print_list(self):
        ### 补充代码 ###
        cur = self.head
        while cur is not None:
            print(cur.data)
            cur = cur.next

    def get_all_data(self):
        ### 补充代码 ###
        data = []
        cur = self.head
        while cur is not None:
            data.append(cur.data)
            cur = cur.next
        return data

2. 删除排序链表中的重复元素

题目简述

给定一个已排序的链表的头head,删除所有重复的元素,使每个元素只出现一次。返回已排序的链表

示例

image-20220330185836695

输入:head = [1,1,2]
输出:[1,2]

思路

采用双指针(precur)的方式,pre指向前一个结点,cur指向后一个结点。如果pre对应的值和cur对应的值相同,则将pre的下一个指针指向cur指向的下一结点,实现删除cur对应位置结点的效果。删除之后,只需要令cur指向pre`的下一个结点即可。如果两个指针指向结点对应的值不相等,只需要向前依次移动两个指针即可。

解决方案

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if (head is None) or (head.next is None):
            return head
        pre = head
        cur = head.next
        while cur != None:
            if pre.val == cur.val:
                pre.next = cur.next
                cur = cur.next
            else:
                pre = cur
                cur = cur.next
        return head

3. 链表中倒数第k个节点

题目简述

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。

示例

给定一个链表: 1->2->3->4->5, 和 k = 2.

返回链表 4->5.

思路

我开始的思路有两种,第一种是直接反转链表,然后按照索引位置寻找出来即可。第二种是根据节点的倒数位置找到节点对应的正向位置,然后只需要找到正向位置的这个节点即可。这里采用第二种方法。

解决方案

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
        pre = head
        count = 0
        #得到所有节点个数
        while pre != None:
            count += 1
            pre = pre.next
        #得到前向传播时我们需要寻找节点的位置
        forward_count = count - k + 1
        cur = head
        count = 0
        #遍历找出该节点
        while cur != None:
            count += 1
            if count == forward_count:
                return cur
            cur = cur.next

4. 删除链表结点

题目简述

给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。

返回删除后的链表的头节点。

**注意:**此题对比原题有改动

示例

输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

思路

采用双指针(pre,cur)解决,pre指向前一节点,cur指向后一节点。如果后一节点的值与我们要删除的值相同,只需要让pre对应的节点的指针域指向cur对应节点的下一节点即可,然后返回。如果不相同,则将两个指针依次向前推进即可。

解决方案

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def deleteNode(self, head: ListNode, val: int) -> ListNode:
        if (head is None) or (head.next is None):
            return head
        if head.val == val:
            head = head.next
            return head
        pre = head
        cur = head.next
        while cur != None:
            if cur.val == val:
                pre.next = cur.next
                return head
            pre = cur
            cur = cur.next

5. 分隔链表

题目简述

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

示例

image-20220330191530745

输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]

思路

创建两个新链表,一个存储比特定值小的节点,一个存储大于等于特定值的节点,最后组合起来即可。

解决方案

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def partition(self, head: ListNode, x: int) -> ListNode:
        p=less=ListNode(0)
        q=more=ListNode(0)

        while head:
            if head.val<x:
                less.next=head
                less=less.next
            else:
                more.next=head
                more=more.next
            head=head.next

        more.next=None
        less.next=q.next
        return p.next

6. 链表求和

题目简述

给定两个用链表表示的整数,每个节点包含一个数位。

这些数位是反向存放的,也就是个位排在链表首部。

编写函数对这两个整数求和,并用链表形式返回结果。

示例

输入:(7 -> 1 -> 6) + (5 -> 9 -> 2),即617 + 295
输出:2 -> 1 -> 9,即912

思路

利用Python列表可以反转的特点,可以先用列表存储各节点元素值。然后再将各节点元素值进行加和操作之后,再翻转一次,创建新的链表存储进去,就可以完成链表形式的返回。(比较繁琐)

解决方案

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        cur1 = l1
        cur2 = l2
        l1_list = []
        l2_list = []
        while cur1 != None:
            l1_list.append(cur1.val)
            cur1 = cur1.next
        while cur2 != None:
            l2_list.append(cur2.val)
            cur2 = cur2.next
        l1_list.reverse()
        l2_list.reverse()
        str1 = ''
        str2 = ''
        for i in l1_list:
            str1 += str(i)
        for i in l2_list:
            str2 += str(i)
        str_end = str(int(str1) + int(str2))
        str_end_list = []
        for i in str_end:
            str_end_list.append(int(i))
        str_end_list.reverse()
        p = ListNode(0)
        pre = p
        for i in str_end_list:
            pre.next = ListNode(i)
            pre = pre.next
        return p.next

7. 回文链表

题目简述

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false

示例

image-20220330192047939

输入:head = [1,2,2,1]
输出:true

思路

利用Python列表可以反转的特点,可以先用列表存储各节点元素值。然后比较列表翻转前和反转后是否一致即可。

解决方案

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        source_list = []
        cur = head
        while cur != None:
            source_list.append(cur.val)
            cur = cur.next
        source_list_zhuan = list(reversed(source_list))
        if source_list_zhuan == source_list:
            return True
        else:
            return False
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值