代码随想录算法训练营第三天 | 203.移除链表元素、707.设计链表 、​ 206. 反转链表​

文章介绍了在链表中移除特定值的元素以及处理头节点的方法,包括使用虚拟头结点简化代码,并提到了反转链表时的双指针策略。作者强调了处理特殊情况和空链表的重要性。
摘要由CSDN通过智能技术生成

203.移除链表元素

1. 第一想法:如何处理好 当前元素和下一个元素的关系。首先要判断虚拟头结点是否为空;

写出来除了判断头结点的方法

接着判断当前元素是否为空,就直接返回,不为空;判断当前元素的下一个元素是否符合条件,不符合条件就只令 当前元素 = 当前元素的下一个元素

就判断当前元素的下一个元素是否符合条件(符合条件就令node.next = node.next.next)

进行下一个循环(继续判断当前元素,因为当前元素的下一个元素是新赋值的)

  • 处理头结点

方法一:单独处理头结点,直到头结点的值不符合条件或者为空

方法二:设置一个虚拟头结点,该头结点一定不符合条件,所以可以统一代码。

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func removeElements(head *ListNode, val int) *ListNode {
    if head == nil{
        return head
    }
    for head.Val == val{
        head = head.Next
        if head == nil{
            return head
        }
    }

    node := head
    for node != nil{
        if node.Next == nil{
            break
        }
        if node.Next.Val == val{
            node.Next = node.Next.Next
            
        }else{
            node = node.Next
        }
        
        
    }
    return head

}

今日收获:处理不好当前元素和下一个元素的关系; 头节点的处理方式,没想到虚拟节点

 707.设计链表 

第一想法:这道题对于我来说不算很难,看了提示,选用使用虚拟头结点练习一下。

不会创建

  • MyLinkedList() 初始化 MyLinkedList 对象。看了一下讲解
  • 先创建一个单节点的结构,再创建一个虚拟头节点的结构,包含一个真正的头结点和链表索引(我使用的时链表索引)
  • 初始化一个链表:使用单节点的结构体创建一个头结点,在创建一个虚拟节点的结构,虚拟节点指向头结点
  • 添加一个节点在头结点  (创建一个新的节点,)
  • 获取一个指定位置的节点(遍历到指定节点的前一个,再获取指定结点的值)
  • 添加一个节点再链表的尾部(不要使用遍历,分情况,如果是空链表就直接添加,如果不是使用判断节点的下一个值是指向nil)
  • 添加一个节点在指定索引的位置(先分情况,再遍历到指定索引的前一个节点)
  • 删除一个指定索引位置的节点()
  • type Node struct{
        Value int
        Next *Node
    }
    type MyLinkedList struct {
        dummyHead *Node
    
        len int
    }
    
    
    func Constructor() MyLinkedList {
        headNode := &Node{
            -999,
            nil,
        }
        mylinke := MyLinkedList{
            dummyHead : headNode,
            len: -1,
        }
        return mylinke
    }
    
    
    func (this *MyLinkedList) Get(index int) int {
         if index > this.len || index < 0{
            return -1
        }
        // 头结点
        node := this.dummyHead
        i := 0
        // 从头结点开始遍历
        for i =0; i < index;i++{
            node = node.Next
        }
        return node.Next.Value
        
        
    
    }
    
    
    func (this *MyLinkedList) AddAtHead(val int)  {
        NewNode := &Node{
            val,
            this.dummyHead.Next,
        }
        this.dummyHead.Next = NewNode
        this.len++
    
    }
    
    
    func (this *MyLinkedList) AddAtTail(val int)  {
        NewNode := &Node{
            val,
            nil,
        }
        node := this.dummyHead
        if node == nil{
            node.Next = NewNode
        }else{
            for node.Next != nil{
                node = node.Next
            }
            node.Next = NewNode
        }
        // for i:=0; i < this.len ;i++{
        //     node = node.Next
        // }
        // for 
        // if node.Next != nil{
        // node.Next.Next = NewNode
    
        // }
        this.len++
    }
    
    
    func (this *MyLinkedList) AddAtIndex(index int, val int)  {
        if index > this.len+1{
            return
        }
        if index == this.len+1{
            this.AddAtTail(val)
            return
    
        }
        if index == 0{
            this.AddAtHead(val)
            return
        }
        NewNode := &Node{
            val,
            nil,
        }
        node := this.dummyHead
        for i:=0; i < index;i++{
            node = node.Next
        }
        NewNode.Next = node.Next
        node.Next = NewNode
        this.len++
    
    }
    
    
    func (this *MyLinkedList) DeleteAtIndex(index int)  {
        if index > this.len{
            return
        }
        node := this.dummyHead
        for i:=0; i < index;i++{
            node = node.Next
        }
        // 有可能删除第一个节点0  此时node就是第一个结点
        if node.Next != nil{
             node.Next = node.Next.Next
        }
        // 此时node是要删除节点的前一个节点
       
        this.len--
        
    
    
    }
    
    
    /**
     * Your MyLinkedList object will be instantiated and called as such:
     * obj := Constructor();
     * param_1 := obj.Get(index);
     * obj.AddAtHead(val);
     * obj.AddAtTail(val);
     * obj.AddAtIndex(index,val);
     * obj.DeleteAtIndex(index);
     */

    不知道为什么 DeleteAtIndex要有判断node.next !=nil 这一步

  • 今日总结:浪费了很多时间写不明白哎

 206. 反转链表

第一想法:反转链表肯定是 让后面的元素 指向 前面的元素,想到了需要保存两个元素,但是没有想到使用双指针,和额外的变量

看到题解后:使用双指针指向前一个元素和后一个元素,并且使用另外一个变量保存后一个元素的下一个元素,方便后移指针。考虑特殊情况 空指针

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseList(head *ListNode) *ListNode {
    //空链表的情况    
    if head == nil{
        return head
    }
    pre := head
    cur := head.Next
    // 链表只有一个值的特殊情况
    if cur == nil{
        return head
    }
    head.Next = nil
    for cur.Next != nil {
        tmp := cur.Next
        cur.Next = pre
        pre = cur
        cur = tmp
    }
    cur.Next = pre
    return cur

}

今日收获:写代码之前考虑了空链表的情况,写代码过程中 发现一个元素的链表的特殊情况也需要额外处理。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值