【代码随想录|链表 203. 移除链表元素,707. 设计链表,206.反转链表】


python

一、链表理论基础

通过指针串联在一起的线性结构,由数据域和指针域组成,最后一个结点的指针域指向null,头节点head
分类:单链表、双链表、循环链表(约瑟夫环问题)

内存非连续

1、链表的定义

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

2、链表的操作

(1)删除结点

只许指针指向下下结点

(2)添加结点

前一个指针指向添加结点,添加结点指针指向下下结点

链表:方便插入删除;数组:方便查询

二、203.移除链表元素

203.移除链表元素

1.核心代码

1、注意点是如果要删除第一个怎么办,所以先设置一个虚拟头结点,vhead.next->head
cur=vhead
2、然后还是判断
while cur.next!= None:
cur->cur.next
if cur.val==val:
cur->next=cur->next->next
return vhead.next

class Solution:
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        # 创建虚拟头部节点以简化删除过程
        dummy_head = ListNode(next = head)
        
        # 遍历列表并删除值为val的节点
        current = dummy_head
        while current.next:
            if current.next.val == val:
                current.next = current.next.next
            else:
                current = current.next
        
        return dummy_head.next

python与c++的区别:用.访问类型的对象,而不是c++中针对指针的->。实际上,在python中,所有的变量都是对对象的引用,相当于都是指针。

注意cur=cur.next必须在val不等下进行!必须在else中!

2.输入输出

在写链表的输入输出时遇到了问题,搜到了卡码网的题解
卡码网github题解
但是只有下一题的输入输出,所以这边先不管,学会下一题的输入输出

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

def removeElements(head, val):
    dummy_head = ListNode(0)
    dummy_head.next = head
    current_node = dummy_head

    while current_node.next is not None:
        if current_node.next.val == val:
            current_node.next = current_node.next.next
        else:
            current_node = current_node.next
    return dummy_head.next

def create_linked_list(elements):
    dummy_node = ListNode(0)
    current_node = dummy_node
    for val in elements:
        current_node.next = ListNode(val)
        current_node = current_node.next
    return dummy_node.next

def print_linked_list(head):
    elements = []
    while head:
        elements.append(head.val)
        head = head.next
    print(' -> '.join(map(str, elements)))

# 从用户那里得到输入
elements = [int(x) for x in input("请输入链表元素,以空格分开:").split()]
val = int(input("请输入要从链表中删除的元素:"))

# 创建链表并删除元素
head = create_linked_list(elements)
head_without_val = removeElements(head, val)

# 输出处理后的链表
print_linked_list(head_without_val)

三、707.设计链表

1、获取下标为index的结点,但是链表没有下标,只能通过指针链接,因此

1、核心代码

class MyLinkedList(object):

    def __init__(self):
        self.size=0
        self.dummyhead=ListNode(0)


    def get(self, index):
        """
        :type index: int
        :rtype: int
        """
        if index>=self.size or index<0:
            return -1
        cur=self.dummyhead.next
        while index:
	        cur=cur.next
	        index-=1
        return cur.val



    def addAtHead(self, val):
        """
        :type val: int
        :rtype: None
        """
        newNode=ListNode(val)
        newNode.next = self.dummyhead.next
        self.dummyhead.next=newNode
        self.size+=1



    def addAtTail(self, val):
        """
        :type val: int
        :rtype: None
        """
        newNode=ListNode(val)
        cur=self.dummyhead
        while cur.next:
            cur=cur.next
        cur.next=newNode
        self.size+=1


    def addAtIndex(self, index, val):
        """
        :type index: int
        :type val: int
        :rtype: None
        """
        if index<=self.size:
            newNode=ListNode(val)
            cur=self.dummyhead
            while index:
                cur=cur.next
                index-=1
            newNode.next=cur.next
            cur.next=newNode
            self.size+=1


    def deleteAtIndex(self, index):
        """
        :type index: int
        :rtype: None
        """
        if index<=self.size-1 and index>=0:
            cur=self.dummyhead
            while index:
                cur=cur.next
                index-=1
            cur.next=cur.next.next
            self.size-=1

链表中的取固定索引都是通过while循环.next操作逐步取到

2、输入输出

链表输入输出特别复杂,我问chatgpt都修正了三四次才得到正确的代码

import ast

#定义链表节点
class LinkedNode:
    def __init__(self, val = 0, next = None):
        self.val = val
        self.next = next

#定义链表基本操作
class MyLinkedList:
    def __init__(self):
        self._size = 0
        self._dummyHead = LinkedNode(0)
    #获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 
    def get(self, index):
  		#省略......
    def addAtHead(self, val):
  		
    def addAtTail(self, val):
        
    def addAtIndex(self, index, val):
        
    def deleteAtIndex(self, index):
        

class LinkedListRunner:
    def __init__(self):
        self.LinkedList = MyLinkedList()
        self.output = []

    def run(self):
        commands = ast.literal_eval(input("Enter your commands: "))
        arguments = ast.literal_eval(input("Enter your arguments: "))

        for cmd, args in zip(commands, arguments):
            cmd = cmd.strip(' ')
            if cmd == "MyLinkedList":
                self.output.append(None)
            elif cmd == "addAtHead":
                self.LinkedList.addAtHead(args[0])
                self.output.append(None)
            elif cmd == "addAtTail":
                self.LinkedList.addAtTail(args[0])
                self.output.append(None)
            elif cmd == "addAtIndex":
                self.LinkedList.addAtIndex(args[0], args[1])
                self.output.append(None)
            elif cmd == "get":
                self.output.append(self.LinkedList.get(args[0]))
            elif cmd == "deleteAtIndex":
                self.LinkedList.deleteAtIndex(args[0])
                self.output.append(None)
            else:
                raise ValueError(f"Command '{cmd}' not recognised.")
        return self.output

if __name__ == '__main__':
    runner = LinkedListRunner()
    print(runner.run())

用户输入输出案例为:
输入:
[“MyLinkedList”,“addAtHead”,“addAtTail”,“addAtIndex”,“get”,“deleteAtIndex”,“get”]
[[],[1],[3],[1,2],[1],[1],[1]]
输出:
[null,null,null,null,2,null,3]

从控制台输入读取命令。ast.literal_eval()是一种安全的方法,可以将输入的字符串(字符串应符合Python字面量语法)解析为Python值。
例如,如果你输入的是[“addAtHead”, “addAtTail”, “get”],ast.literal_eval()会将其解析为Python的列表结构:[‘addAtHead’, ‘addAtTail’, ‘get’]。
同样,如果输入的是"[1, 2, 3]",ast.literal_eval()将其解析为Python的列表[1, 2, 3]。

ast 是 Python 的一个内置模块,名字的全称是 Abstract Syntax Trees(抽象语法树)。这个模块可以把 Python 代码转化为抽象语法树,或者把抽象语法树转化为 Python 代码。

在Python中,zip函数将多个可迭代对象打包成一个元组的迭代器。每个迭代器中的元素由输入的可迭代对象中相应位置上的元素组成。

.strip(’ '):这是对字符串进行操作的一个方法。strip() 方法用于移除字符串头尾指定的字符(默认为空白符,包括空格、换行符、制表符等)。
’ ':这是strip()方法的参数,指定了需要去除的字符。在这个例子中,我们指定去除空格字符。
如果字符串 cmd 的两侧有空格,使用这个方法后,这些空格会被去掉,但字符串中间的空格不会被影响。

(1)print() 表示换行
(2)print(x,end=‘’)表示以’ '隔开
(3)while Ture 程序进入一个死循环,除非程序异常或者主动退出
(4)初始化要记得
(5)try:xxx except:xxx 是程序遇到错误的跳转模块,可以由多个except对应多个错误
(6)append在列表的末尾添加

3、其他问题

python中报黄线:
(1)没打空格:可以用ctrl+alt+L,一键自动排版
(2)def的函数不建议用大写,建议用下划线 def name_what 与类 class nameWhat 进行区分

Python2 和 Python3 是 Python 语言的两个主要版本,它们之间存在一些重要的差异:
打印语句:在 Python2 中,print 是一个语句,你可以直接使用 print “Hello World” 就可以打印内容。但在 Python3 中,print 成了一个函数,你需要使用 print(“Hello World”)。
整数除法:在 Python2 中,两个整数相除的结果会自动取整,例如:5 / 2 = 2。但在 Python3 中,两个整数相除的结果会保留小数,例如:5 / 2 = 2.5。
Unicode:Python3 支持 Unicode,可以处理更多的文本数据。在 Python2 中,字符串默认是 ASCII 编码的,需要加u前缀创建 Unicode 字符串,如 u"hello"。
xrange : 在 Python2 中有 range 和 xrange,xrange比range效率更高,因为不会引发内存溢出。但是在 Python3 中,range 函数已经是像 xrange 那样进行优化,而且xrange已经不存在了。
异常处理:Python2中使用 raise ValueError, “math domain error” 或者 raise ValueError(“math domain error”) 来抛出异常,同时使用 , 来从异常中捕获相关变量。Python3中使用 raise ValueError(“math domain error”) 来抛出异常,同时使用 as 来从异常中捕获相关变量。
这只是 Python2 和 Python3 之间的一部分差异。虽然 Python2 继续得到支持,但 Python3 是 Python 的未来,如果你正在学习 Python 或者开发新的项目,我建议你使用 Python3。

三、206.反转链表

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:
        cur = head   
        pre = None
        while cur:
            temp = cur.next # 保存一下 cur的下一个节点,因为接下来要改变cur->next
            cur.next = pre #反转
            #更新pre、cur指针
            pre = cur
            cur = temp
        return pre

说是双指针,其实还保存了一个temp变量

基本思想比较简单

2、输入输出

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

def reverseList(head: ListNode) -> ListNode:
    previous = None
    current = head
    while current:
        next_temp = current.next
        current.next = previous
        previous = current
        current = next_temp
    return previous

def create_list(nums: list) -> ListNode:
    dummy = ListNode(0)
    ptr = dummy
    for num in nums:
        ptr.next = ListNode(num)
        ptr = ptr.next
    return dummy.next

def list_to_array(head: ListNode) -> list:
    arr = []
    ptr = head
    while ptr:
        arr.append(ptr.val)
        ptr = ptr.next
    return arr

# 获取用户输入,例如:head = [1,2,3,4,5]
input_str = input("请输入链表,格式为 head = [1,2,3,4,5]:")

# 解析输入字符串,提取数字列表
nums_str = input_str[input_str.find("[")+1:input_str.find("]")]
nums_list = list(map(int, nums_str.split(',')))

# 根据数字列表创建链表
head = create_list(nums_list)

# 反转链表
reversed_head = reverseList(head)

# 将反转后的链表转换成列表形式并输出
print("输出:", list_to_array(reversed_head))

nums_str = input_str[input_str.find(“[”)+1:input_str.find(“]”)] 用find定位

总结

链表的输入输出是重点
输入字符串——变为列表——变为链表——核心代码——变为列表输出
变为链表:用指针串起来
变为列表:把值一个个加在list后面

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值