代码随想录算法训练营Day3 | LeetCode203 移除链表元素、LeetCode707 设计链表、LeetCode206 反转链表

Posted by 慕念 on February 23, 2024

链表理论基础

文章链接:https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

C++的定义链表节点方式:

// 单链表
struct ListNode {
    int val;  // 节点上存储的元素
    
    ListNode *next;  // 指向下一个节点的指针
    
    ListNode(int x) : val(x), next(NULL) {}  // 节点的构造函数
    
};

ListNode* head = new ListNode(5);
// 或
ListNode* head = new ListNode();
head->val = 5;

python:

class ListNode:
    def __init__(self, val, next=None):
        self.val = val
        self.next = next

C:

typedef struct ListNodeT {
    int val;
    struct ListNodeT next;
} ListNode;

删除节点

删除D节点,如图所示:

链表-删除节点

添加节点

如图所示:

链表-添加节点

性能分析

再把链表的特性和数组的特性进行一个对比,如图所示:

链表-链表与数据性能对比

LeetCode203 移除链表元素

题目链接/文章讲解/视频讲解::https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.htmlhttps://www.bilibili.com/video/BV1QB4y1D7ep )

增加虚拟头节点:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        newhead = ListNode(next = head)
        current = newhead

        while current.next:
            if current.next.val == val: # 要删除的节点
                
                current.next = current.next.next
            else:
                current = current.next
        return newhead.next
        

增加虚拟头节点,可以对所有节点统一处理,如果不增加,需要对头节点和不是头节点的元素分别讨论

LeetCode707 设计链表

题目链接/文章讲解/视频讲解:

https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html

⭐定义节点ListNode具有数据val和next,同时MyLinkedList里面含一个计数器 方便插入删除

⭐注意边界

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
        
class MyLinkedList:
    def __init__(self):
        self.dummy_head = ListNode()	# 虚拟头指针
        
        self.size = 0

    def get(self, index: int) -> int:
        if index < 0 or index >= self.size:
            return -1
        
        current = self.dummy_head.next	# 指向next,index=0时直接指向head
        
        for i in range(index):
            current = current.next
            
        return current.val

    def addAtHead(self, val: int) -> None:
        self.dummy_head.next = ListNode(val, self.dummy_head.next)
        self.size += 1

    def addAtTail(self, val: int) -> None:
        current = self.dummy_head
        while current.next:
            current = current.next
        current.next = ListNode(val)
        self.size += 1

    def addAtIndex(self, index: int, val: int) -> None:
        if index < 0 or index > self.size:
            return
        
        # 插入current和current.next之间(第n个节点是current.next)
        
        current = self.dummy_head
        for i in range(index):
            current = current.next
        current.next = ListNode(val, current.next)
        self.size += 1

    def deleteAtIndex(self, index: int) -> None:
        if index < 0 or index >= self.size:
            return
        
        # 通过操作current删除current.next(第n个节点是current.next)
        
        current = self.dummy_head
        for i in range(index):
            current = current.next
        current.next = current.next.next
        self.size -= 1


# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)

LeetCode206 反转链表

双指针

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        current = head
        pre = None  # pre指向current前一个

        while current:  # 当current为null时停止遍历
            
            tmp = current.next
            current.next = pre  # 改变方向
            
            pre = current   # per和current都向后移动一位
            
            current = tmp
        return pre  # pre指向新链表头节点
        

递归