Leetcode部分链表相关练习
一、链表
借鉴[https://blog.csdn.net/dzysunshine/article/details/88041673]
1.实现单链表、循环链表、双向链表,支持增删操作
class LNode: # 定义节点类
def __init__(self, elem, next_=None):
self.elem = elem
self.next = next_
class LList: # 定义单链表类
def __init__(self):
self._head = None
# 增,包括链表头、尾和中间位置三种方法
def prepend(self, elem):
self._head = LNode(elem)
def append(self, elem):
if not self._head:
self._head = LNode(elem)
return
p = self._head
while p.next:
p = p.next
p.next = LNode(elem)
def insert(self, elem, key):
tmp = LNode(elem)
p = self._head
for i in range(key-1):
p = p.next
tmp.next = p.next
p.next = tmp
# 删,也是三种方法
def delete(self, key):
# todo: key边界限制待添加
p = self._head
for i in range(key - 1):
p = p.next
p.next = p.next.next
def print_all(self):
p = self._head
while p :
print(p.elem, end='')
if p.next:
print('->', end='')
p = p.next
print('')
class CList: # 定义循环链表类
def __init__(self):
self._head = LNode(None)
self._head.next = self._head
self._rear = self._head
def insert(self, key, value):
tmp = LNode(elem)
p = self._head
for i in range(key-1):
p = p.next
tmp.next = p.next
p.next = tmp
if tmp.next == self._head:
self._rear = tmp
def delete(self, key):
# todo:key边界
p = self._head
for i in range(key-1):
p = p.next
if not p:
print('WRONG POSITION!')
return
tmp = p.next
p.next = p.next.next
del tmp
if p.next ==self._head:
self._rear = p
class DLNode(LNode): # 定义双链表节点
def __init__(self, elem, next_=None, prev=None):
super(DLNode, self).__init__()
self.prev = prev
if __name__ == '__main__':
l = LList()
for i in range(10):
l.append(i)
l.print_all()
l.insert(50, 3)
l.print_all()
l.delete(10)
l.print_all()
2.实现单链表反转
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
prev = None
cur = head
while cur:
nxt = cur.next
cur.next = prev
prev = cur
cur = nxt
return prev
3.实现两个有序的链表合并为一个有序链表
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
l3 = ListNode(0)#空链表
cur = l3
while (l1 != None) & (l2!=None):
if l1.val <= l2.val:
cur.next = l1
l1 = l1.next
else:
cur.next = l2
l2 = l2.next
cur = cur.next
if l1 != None:
cur.next = l1
if l2 != None:
cur.next = l2
l3 = l3.next
return l3
4.实现求链表的中间结点
def find_middle_node(head):
slow, fast = head, head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
return slow
练习
141. 环形链表
[https://leetcode-cn.com/problems/linked-list-cycle/submissions/]
题目描述
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
示例 1:
输入:head = [3,2,0,4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
解题思路
设定快慢指针,快指针每次跨越两格,慢指针每次跨越一格,如果两个指针有重合的时候,该链表就存在环。
代码实现
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
fast = slow = head
while slow and fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow is fast:
return True
return False
23. 合并K个排序链表
[https://leetcode-cn.com/problems/merge-k-sorted-lists/comments/]
题目描述
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
代码实现
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
r, n, p = [], lists and lists.pop(), None
while lists or n: r[len(r):], n = ([n], n.next or lists and lists.pop()) if n else ([], lists.pop())
for n in sorted(r, key=lambda x: x.val, reverse=True): n.next, p = p, n
return n if r else []