代码随想录算法训练营|Day3|移除链表|设计链表|反转链表

Leetcode 203 移除链表元素

  • 题目链接

  • 主要思想

    • 常规
      • 非头 head 节点
        找到要移除节点的前一个节点,指向要移除节点的下一个节点

      • 移除头部节点
        Head 节点:将head 移到下一节点,head = head.next

    • 改进
      • 虚拟头节点方法
        • Why:上述删除有两种情况,这里想统一这两种情况的代码
  • 操作

    • Method1:直接删除
      1. 先判断要删的元素是否为head 节点
      • 判断条件:头节点是否为空 & 头节点所指向的数值 = target 要删除的数值
      • 操作:头节点指向下一个,head = head -> next
        在这里插入图片描述

df

2.  删除非头节点的指针
-- 伪代码
while (head != null) & (head -> val == target):   // 持续移除头节点
    head = head.next
 
  • 代码
  1. 两步法
class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        while (head != None) and (head.val == val):
            head = head.next 
        # other nodes 
        cur = head
        while (cur != None) and (cur.next != None):
            if cur.next.val == val:
                cur.next = cur.next.next 
            else:
                cur = cur.next 
        return head 
  • trick点
# 1. 第一个 while 的使用
## 错误写法:会导致超时;这种情况下,可以直接在条件部分就进行判断
while (head != None) and (head.next != None):
	 if head.val == val:
	     head = head.next  # 会导致超时
# 2. cur.next 和 cur.next.next 
## 错误写法:会导致最后1个6没有处理,因为cur.next.next == None
 
cur = head
while (cur.next != None) and (cur.next.next != None): # 当cur = 5时,因为 cur.next.next is null, 所以没有处理最后一个6,就直接结束了while 循环
    if cur.next.val == val:
        cur.next = cur.next.next 
    else:
        cur = cur.next 
return head 

在这里插入图片描述

  1. 虚拟头节点
class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        dummy_head = ListNode(next = head)
        cur = dummy_head
        while cur.next != None:
            if cur.next.val == val:          # 补充.val,之前只写了cur.next
                cur.next = cur.next.next
            else:
                cur = cur.next 
        return dummy_head.next 
  • tricky点
    • cur.next 加上.val

Leetcode 707 设计链表

# 单链表

class MyLinkedList:

    def __init__(self):
        # self.val = val
        # self.next = None 
        self._head = ListNode(0)  # 虚拟头部节点, val = 0 
        self._count = 0  # 初始状态 count = 0 

    def get(self, index: int) -> int:
        if 0 <= index < self._count:  # self._count = index + 1 
            cur = self._head.next 
            while index > 0 :
                cur = cur.next 
                index -= 1 
            return cur.val 
        else:
            return -1 

    def addAtHead(self, val: int) -> None:
        self._count += 1 
        add_node = ListNode(val)
        add_node.next = self._head.next
        self._head.next = add_node
    
    # def addAtHead(self, val: int) -> None:
    #     """
    #     Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
    #     """
    #     self.addAtIndex(0, val)

    def addAtTail(self, val: int) -> None:
        self._count += 1 
        cur = self._head
        while cur.next != None:
            cur = cur.next 
        add_node = ListNode(val)
        cur.next = add_node
    
    # def addAtTail(self, val: int) -> None:
    #     """
    #     Append a node of value val to the last element of the linked list.
    #     """
    #     self.addAtIndex(self._count, val)

    def addAtIndex(self, index: int, val: int) -> None:
        if index < 0 :
            index = 0 
        elif index > self._count:
            return 
        else: 
            self._count += 1 
            add_node = ListNode(val)
            # prev, cur = self._head, self._head.next  index = 0 的话需要另行考虑
            prev, cur = None, self._head
            # 寻找第 index 个节点                
            for _ in range(index + 1):  
                prev, cur = cur, cur.next  # 错误: prev, cur = prev.next, cur.next; prev = None
            # add node 
            add_node.next = cur
            prev.next = add_node   

    # def addAtIndex(self, index: int, val: int) -> None:
    #     """
    #     Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
    #     """
    #     if index < 0:
    #         index = 0
    #     elif index > self._count:
    #         return

    #     # 计数累加
    #     self._count += 1

    #     add_node = ListNode(val)
    #     prev_node, current_node = None, self._head
    #     for _ in range(index + 1):
    #         prev_node, current_node = current_node, current_node.next
    #     else:
    #         prev_node.next, add_node.next = add_node, current_node

    def deleteAtIndex(self, index: int) -> None:
        if 0 <= index < self._count:
            self._count -= 1 
            prev, cur = None, self._head
            # 寻找第 index 个节点                
            for _ in range(index + 1):  
                prev, cur = cur, cur.next  # 错误: prev, cur = prev.next, cur.next; prev = None
            # delete node 
            prev.next = cur.next 
        else:
            return -1 

    # def deleteAtIndex(self, index: int) -> None:
    #     """
    #     Delete the index-th node in the linked list, if the index is valid.
    #     """
    #     if 0 <= index < self._count:
    #         # 计数-1
    #         self._count -= 1
    #         prev_node, current_node = None, self._head
    #         for _ in range(index + 1):
    #             prev_node, current_node = current_node, current_node.next
    #         else:
    #             prev_node.next, current_node.next = current_node.next, None


Leetcode 206 反转链表

  • 思想
    • raw:定义一个新链表 -> 浪费内存空间
    • now:只需要改变链表的next指针的指向,直接将链表反转
  • 解法
    1. 双指针
    • General
      1. 双指针
      • cur指针,指向头结点
      • 定义一个pre指针,初始化为null,定义在cur前面,以便于反转
      1. pre 和 cur 指针不断向后移动;每移动一次,改变cur与pre之间的指针方向
    • 细节
      • pre 初始化为null,因为反转后head指向null
      • 遍历结束:pre = 尾节点,cur = None时
        • While cur
        • 结果:pre称为新链表的头节点
      • 赋值
        • 临时指针:temp = cur.next;防止指向pre节点时,cur与cur.next没有指针连接

        • 反转后,先移动pre,后移动cur

          • Pre = cur
          • Cur = temp
# 双指针
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        cur = head   
        pre = None
        while(cur != None):
            temp = cur.next # 保存一下 cur的下一个节点,因为接下来要改变cur->next
            cur.next = pre #反转
            #更新pre、cur指针
            pre = cur
            cur = temp
        return pre
  1. 递归法
  • 主要是根据双指针方法改写
    • 注意终止条件
    • 赋值 = 函数中的参数
# 递归
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        
        def reverse(pre,cur):
            if not cur:
                return pre
                
            tmp = cur.next
            cur.next = pre
            return reverse(cur,tmp)
        
        return reverse(None,head)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值