GIS与Climate

V1

2022/09/23阅读:23主题:默认主题

算法60天:Day 3-链表初识

代码随想录(截图自参考【1】)
代码随想录(截图自参考【1】)

本系列是代码随想录算法训练营的学习笔记之day3,主要记录一下刷题的过程,以及核心知识点和一些值的记录的问题。

代码随想录的资源都是免费的,具体可以看参考链接【1】。

今日知识点

链表理论基础:

  • 链表是一种串联、线性结构
  • 每个节点有两部分组成,值域和指针域,指针域存放指向下一个节点的指针;
  • 最后一个节点的指针域指向null(注意不同语言的写法,比如python是None);

今日题目

  1. 移除链表元素(203)

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

链接:https://leetcode.cn/problems/remove-linked-list-elements/

解题思路

  • 需要删除所有满足条件的节点,所以在循环中要遍历到所有的节点;
  • 对于链表的增删,因为要考虑到是否是首节点,所以增加虚拟节点,具体的可以看Carl师兄的讲解;
  • 删除当前节点就相当于跳过当前节点,只需要修改上一个节点的指针域即可;
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        vir_ln = ListNode(next=head)
        cur = vir_ln
        while cur.next!=None:
            if cur.next.val==val:
                cur.next = cur.next.next
            else:
                cur = cur.next
        return vir_ln.next
  • 要注意要返回的是头结点!
  1. 设计链表(707)

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val  的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

链接:https://leetcode.cn/problems/design-linked-list/

解题思路

  • 这道题个人认为比较难,就是实现链表的各种功能,按照题目要求一个个写就行,但是需要考虑清楚题目中说的特殊情况,比如索引无效的时候返回-1,插入节点的时候如果index大于链表长度就不会插入节点(返回空);
  • 在头部插入和在尾部插入节点是在特定index插入节点的特殊情况;
  • 在插入节点之后要更新链表的节点数量,否则后续就无法操作;
class Node:
    def __init__(self,val):
        self.val = val
        self.next = None

class MyLinkedList:

    def __init__(self):
        self._head = Node(0)
        self._count = 0
        

    def get(self, index: int) -> int:
        if 0<= index < self._count:
            node = self._head
            for _ in range(index+1):
                node = node.next
            return node.val
        else:
            return -1
        


    def addAtHead(self, val: int) -> None:
        self.addAtIndex(0,val)


    def addAtTail(self, val: int) -> None:
        self.addAtIndex(self._count,val)


    def addAtIndex(self, index: int, val: int) -> None:
        if index<0:
            index =0
        elif index>self._count:
            return
        
        self._count += 1

        add_node = Node(val)
        pre_node, cur_node = None, self._head
        for _ in range(index+1):
            pre_node, cur_node = cur_node,cur_node.next
        else:
            pre_node.next, add_node.next = add_node, cur_node


    def deleteAtIndex(self, index: int) -> None:
        if 0 <= index < self._count:
            self._count -= 1
            pre_node,cur_node = None, self._head
            for _ in range(index+1):
                pre_node,cur_node = cur_node,cur_node.next
            else:
                pre_node.next,cur_node.next = cur_node.next, None



# 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)

(上面的代码写的还不够熟悉,有些在写的时候就写不出来了。。。)

  1. 反转链表(206)

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

链接:https://leetcode.cn/problems/reverse-linked-list/

解题思路

  • 这道题理解起来比较简单,就是修改下链表中指针的方向;
  • 操作的时候注意使用中间变量,否则不保存当前节点的原始指针的话,无法往后遍历链表;
  • 另外就是注意while的循环条件要用cur!=None,否则无法遍历到最后一个节点;
  • 返回的头节点是最后一个pre!
# 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: Optional[ListNode]) -> Optional[ListNode]:
        pre = None
        cur = head

        while cur != None:
            temp = cur.next
            cur.next = pre 
            pre = cur
            cur = temp
        
        return pre 
            

补充知识点

  1. 链表的几种类型

上面说的是最简单的链表,实际上链表有几种:

  • 单链表
单链表
单链表
  • 双链表:一个节点有两个指针域,分别指向前一个和后一个节点;
双链表
双链表
  • 循环链表:单链表的特殊情况,首尾相连。
循环链表
循环链表
  1. 链表的存储方式

数组在内存中是连续存储的,但是链表不是,因为链表有指针,可以顺利找到下一个元素。

  1. 链表与数组的性能分析

今日思考

  1. 怎么形象理解链表中的插入和删除?

想象一个N个同学手拉手的样子,然后中间插入新同学和踢出旧同学。。。

参考

【1】代码随想录:https://programmercarl.com/

分类:

后端

标签:

数据结构与算法

作者介绍

GIS与Climate
V1

公众号:GIS与Climate,欢迎关注