day3 | 203. 移除链表元素,206. 反转链表,707. 设计链表

203. 移除链表元素

 

题目描述

 

给你一个链表的头节点head和一个整数val,删除链表中的那些存储的值为val的节点,并且返回新的头节点。

 

思路:

 

1. 创建一个虚拟头节点,取名为ptr1,指向head,另外再创建一个节点cur和ptr1相等,也指向head

2. 利用cur进行遍历,这里cur最开始并不能取为head,而是应该取为虚拟头节点,是因为当链表为空时,头节点是null,并没有next属性,会报错,而虚拟头节点有next属性,可以指向None或者指向null类型的。

3. 进入循环,不断判断cur所指向的下一个节点里面存的值是不是val,如果是,则把cur所指向的节点往后调一个。

4. 当下一个节点存的值不是val,就放心让cur成为下一个节点。

5. 因为cur从一开始就不存有val,那么一直变换下去,也不会存有val。

 

代码如下:

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

 

 

206. 反转链表

 

题目描述

 

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

 

思路

1. 链表中的最后一个节点指向None,所以先创建一个None

2. 取第1个节点,使其指向None;再去取第2个节点,使其指向第1个节点......如此遍历下去

3. head指向节点1,意味着 head.value=1, head.next指向结点2,head.next.value=2,y以此类推

4. 在使第1个节点指向None的时候,需要提前存好第2个节点的地址信息,新建一个变量来存这个信息,然后再把第一个节点指向None,意味着先用 temp=cur.next 存好原来的第2个节点地址信息,再用 cur.next=pre 指向None

5. 做完上一步后,为了持续迭代,为了使第2个节点指向第1个节点,需要一个变量存第1个节点的地址信息,刚好就用pre,

而cur此时存有第1个节点的地址信息,用 pre=cur 便可以把第一个节点的地址信息保存下来

6. cur=temp ,用存在temp中第2个节点的地址信息改变  cur 的值,使得迭代可以进行

7. 如此循环往复

代码如下

 

# 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

 

 

 

707. 设计链表

 

题目描述

 

 

 

思路

 由于该类定义中增加了链表长度的计数,所以每次进行链表节点增删的时候,都记得对计数长度len进行更改。

1. 初始化,定义一个虚拟头节点,指向头节点;再定义一个count_node,用来记录有多少个节点

2. 获得第index节点的值,由于节点下标从0开始,当index取count_node时,实际是第count_node+1个节点,越界了,所以等号也不能取

3. dummy.next为head头节点,而head.value就是第1个节点的值,head.next.value是第2个节点的值;可以理解为head.value指向并取第1个节点的值,head.next是第1个节点内存有的第2个节点的地址信息,并可以通过其访问第2个节点内的信息,比如head.next.value=2。如下图所示结构,head里面有next和value,而这个next里面又有next和value,如此,直到next=None为止。

 

 

 

 

 

 

 

 

 

 

 

 

4. addAtIndex函数,同样注意index从0开始即可

算法实现代码如下

class MyLinkedList:

    def __init__(self):
        self.dummy=ListNode() # 定义虚拟头节点,指向头节点
        self.count_node=0

    def get(self, index: int) -> int:
        if index<0 or index>=self.count_node: # 链表下标从0开始,所以当index取count_node,实际是第count_node+1个点,越界了
            return -1
        cur=self.dummy.next
        for _ in range(index):
            cur=cur.next
        return cur.val

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



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


    def addAtIndex(self, index: int, val: int) -> None:
        if index>self.count_node:
            return
        pre=self.dummy
        for _ in range(index): # 循环1次,指向第0个节点;循环index次,指向第index-1个节点
            pre=pre.next
        pre.next=ListNode(val,pre.next) # pre指向一个新的节点,而这个新的节点的值为val,并指向pre节点原来指向的节点
        self.count_node+=1
        


    def deleteAtIndex(self, index: int) -> None:
        if index>=self.count_node:
            return
        pre=self.dummy
        for _ in range(index):
            pre=pre.next

        t=pre.next # t指向第index个节点
        pre.next=t.next # 用pre接收第index节点指向的下一个位置上的节点
        t.next=None
        self.count_node-=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)

 

总结

 

1. 熟练掌握虚拟头节点

2. 掌握next和value的含义

3. 掌握链表是怎么连起来的

4. 借助pycharm了解链表的内部结构,实现在电脑中的结构是如何的,便于理解

posted @ 2023-03-17 20:42  blueCP1999  阅读(25)  评论(0)    收藏  举报