蓝桥杯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
用于指定结点的数据元素,它需要返回插入的结点。如果data
为None
则返回None
。LinkedList
中的append
方法用于在链表后面增加结点,参数data
用于指定结点的数据元素,它需要返回增加的结点。如果data
为None
则返回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
,删除所有重复的元素,使每个元素只出现一次。返回已排序的链表
示例
输入:head = [1,1,2]
输出:[1,2]
思路
采用双指针(pre
,cur
)的方式,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 的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置。
示例
输入: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
。
示例
输入: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