代码随想录算法训练营Day3 | 链表(1/2) LeetCode 203.移除链表元素 707.设计链表 206.反转链表

链表知识点

在开始前,我们先回顾一下链表的一些知识点。

一、链表是什么


 1.定义:链表(Linked list)是一种常见的基础数据结构,是一种线性表,在每一个节点(数据存储单元)里存放下一个节点的位置信息

2.优点:顺序表的构建需要预知数据大小来申请连续存储空间,扩充时需要进行数据迁移,使用不灵活,链表充分利用计算机内存空间,实现灵活内存动态管理
 

二、单向列表

1.定义:单向链表(单链表)是链表中最简单一种形式,它的每个节点包含两个域——信息域(元素域)和链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。

 

head 保存首地址,elem 存储数据,next 指向下一结点地址。

2.相关方法

方法说明
s_empty()链表是否为空
length()链表长度
travel()遍历整个链表
add(item)链表头部添加元素
append(item)链表尾部添加元素
insert(pos,item)在指定位置添加元素
remove(item)删除节点
search(item)查找结点是否存在

3. 代码实现 

#定义节点
class Node(object):
    def __init__(self,elem):
        self.elem=elem
        self.next=None
#构造单向链表
class SingleLinkedList:
    #判断链表是否为空:_head指向None,则为空
    def is_empty(self):
        '''
        if self._head==None:
            print("True")
        else:
            print("False")
            '''
        return self._head==None
    #单向链表初始化
    def __init__(self,node=None):
        #判断node是否为空
        if node!=None:
            headNode=Node(node)
            self._head=headNode
        else:
            self._head=node
    #计算链表长度
    def length(self):
        count=0
        curNode=self._head
        while curNode!=None:
            count+=1
            curNode=curNode.next
            return count
    #遍历链表
    def travel(self):
        curNode=self._head
        while curNode!=None:
            print(curNode.elem,end='\t')
            curNode=curNode.next
        print("  ")
    #在头部添加元素
    def add(self,item):
        #将传入的值构造成节点
        node=Node(item)
        #将新节点的链接域next指向头节点
        node.next=self._head
        #将链表的头_head指向新节点
        self._head=node
    #在尾部添加元素
    def append(self,item):
        #将传入的值构造成节点
        node=Node(item)
        if self.is_empty(): #单链表为空
            self._head=node
        else: #单链表不为空
            curNode=self._head
            while curNode.next!=None:
                curNode=curNode.next
            #修改节点,最后一个节点的next指向node
            curNode.next=node
 
    #在指定位置添加元素
    def insert(self,pos,item):
        #如果pos<=0,默认插入到头部
        if pos<=0:
            self.add(item)
        #如果pos>链表长度,直接在尾部追加
        elif pos>(self.length()-1):
            self.append(item)
        else:
            #构造节点
            node=Node(item)
            count=0
            preNode=self._head
            while count<(pos-1): #查找前一个节点
                count+=1
                preNode=preNode.next
            #修改指向
            #将前一个节点的next指向插入节点
            node.next=preNode.next
            #将插入位置的前一个节点next指向新节点
            preNode.next=node
 
    #查找节点是否存在
    def search(self,item):
        curNode=self._head
        while curNode!=None:
            if curNode.elem==item:
                return True
            curNode=curNode.next
        return False
    #删除节点
    def remove(self,item):
        curNode=self._head
        preNode=None
        while curNode!=None:
            if curNode.elem==item:
                #判断是否是头节点
                if preNode==None:#是头节点
                    self._head=curNode.next
                else:
                    #删除
                    preNode.next=curNode.next
            break
        else:
                preNode=curNode
                curNode=curNode.next
if __name__=="__main__":
    #初始化元素值为10单向链表
    singleLinkedList=SingleLinkedList(30)
    print("是否为空链表:",singleLinkedList.is_empty())
    print("链表长度为:",singleLinkedList.length())
    print("----遍历链表----")
    singleLinkedList.travel()
    print("-----查找-----",singleLinkedList.search(30))
    print("-----头部插入-----")
    singleLinkedList.add(1)
    singleLinkedList.add(2)
    singleLinkedList.add(3)
    singleLinkedList.travel()
    print("-----尾部追加-----")
    singleLinkedList.append(10)
    singleLinkedList.append(20)
    singleLinkedList.travel()
    print("-----链表长度-----",singleLinkedList.length())
    print("-----指定位置插入-----")
    singleLinkedList.insert(-1,100)
    singleLinkedList.travel()
    print("-----删除节点-----")
    singleLinkedList.remove(100)
    singleLinkedList.travel()
三、双向链表

 1. 双向链表是一种更复杂的链表。每个节点有两个链接:一个指向前一个节点,当此节点为第一个节点时,指向空值,而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。

2. 代码实现

class Node:
    def __init__(self,elem):
        self.elem=elem
        self.next=None #下一个节点
        self.prev=None #前一个节点
 
class DoubleLinkedList:
    # 双向链表初始化
    def __init__(self, node=None):
        # 判断node是否为空
        if node != None:
            headNode=Node(node)
            self._head=headNode
        else:
            self._head=node
    def is_empty(self):
        '''
        if self._head==None:
            print("True")
        else:
            print("False")
            '''
        return self._head==None
    #计算链表长度
    def length(self):
        count=0
        curNode=self._head
        while curNode!=None:
            count+=1
            curNode=curNode.next
            return count
    #遍历链表
    def travel(self):
        curNode=self._head
        while curNode!=None:
            print(curNode.elem,end='\t')
            curNode=curNode.next
        print("  ")
    #在头部添加元素
    def add(self,item):
        #判断是否空链表
        node = Node(item)
        if self.is_empty():
            self._head=node
        else:
            #将传入的值构造成节点
            node=Node(item)
            #将新节点的链接域next指向头节点
            node.next=self._head
            #将_head的头节点的prev指向node
            self._head.prev=node
            #将链表的头_head指向新节点
            self._head=node
    #在尾部追加元素
    def append(self,item):
        #将传入的值构造成节点
        node=Node(item)
        if self.is_empty(): #双向链表为空
            self._head=node
        else: #双向链表不为空
            curNode=self._head
            while curNode.next!=None:
                curNode=curNode.next
            #修改节点,最后一个节点的next指向node
            curNode.next=node
            #将node节点的前驱指向当前节点
            node.prev=curNode
 
    #在指定位置添加元素
    def insert(self,pos,item):
        #如果pos<=0,默认插入到头部
        if pos<=0:
            self.add(item)
        #如果pos>链表长度,直接在尾部追加
        elif pos>(self.length()-1):
            self.append(item)
        else:
            #构造节点
            node=Node(item)
            count=0
            curNode=self._head
            while count<(pos-1): #查找前一个节点
                count+=1
                curNode=curNode.next
            #修改指向
            #node节点前驱指向当前节点
            node.prev=curNode
            #node节点的next指向当前节点的下一个节点
            node.next=curNode.next
            #当前节点的下一个节点的前驱指向node节点
            curNode.next.prev=node
            #当前节点的下一个节点指向node节点
            curNode.next=node
 
    #查找节点是否存在
    def search(self,item):
        curNode=self._head
        while curNode!=None:
            if curNode.elem==item:
                return True
            curNode=curNode.next
        return False
    #删除节点
    def remove(self,item):
        curNode=self._head
        while curNode!=None:
            if curNode.elem==item:
                #判断是否是头节点
                if curNode==self._head:#是头节点
                    self._head=curNode.next
                    #判断当前节点是否只有一个节点
                    if curNode.next:
                        curNode.next.prev==None
                else:
                    #删除
                    curNode.prev.next=curNode.next
                    #判断当前节点是否是最后一个节点,若是,不需要移动下一个
                    if curNode.next:
                        curNode.next.prev=curNode.prev
            break
        else:
                curNode=curNode.next
if __name__=="__main__":
    doubleLinkedList=DoubleLinkedList()
    print("-----头部添加-----")
    doubleLinkedList.add(11)
    doubleLinkedList.add(22)
    doubleLinkedList.add(33)
    doubleLinkedList.travel()
    print("-----尾部追加-----")
    doubleLinkedList.append(44)
    doubleLinkedList.travel()
    print("指定位置插入")
    doubleLinkedList.insert(3,100)
    doubleLinkedList.travel()
    print("-----删除元素-----")
    doubleLinkedList.remove(33)
    doubleLinkedList.travel()

第一题

203. Remove Linked List Elements

Given the head of a linked list and an integer val, remove all the nodes of the linked list that has Node.val == val, and return the new head.

 思路:链表有空链表和非空链表两种。对于非空链表,第一个节点的操作和后面的有所不同。而在头节点前面加一个虚拟节点(dummy),这样可以让头节点变得和后面的节点一样。

# 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]:
        dummy = ListNode(next = head)
        cur = dummy
        while cur.next!=None:
            if cur.next.val == val:
                cur.next = cur.next.next
            else:
                cur = cur.next

        return dummy.next

第二题

707. Design Linked List

Design your implementation of the linked list. You can choose to use a singly or doubly linked list.
A node in a singly linked list should have two attributes: val and nextval is the value of the current node, and next is a pointer/reference to the next node.
If you want to use the doubly linked list, you will need one more attribute prev to indicate the previous node in the linked list. Assume all nodes in the linked list are 0-indexed.

代码随想录 707 解析https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE看了看解析,有了大概思路

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

第三题

206. Reverse Linked List

Given the head of a singly linked list, reverse the list, and return the reversed list.

 只需要改变链表的next指针的指向,直接将链表反转 ,而不用重新定义一个新的链表

双指针法可以做出来

# 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]:
        cur = head   
        pre = None
        while cur:
            temp = cur.next 
            cur.next = pre 
            pre = cur
            cur = temp
        return pre

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值