三、移除链表元素 设计链表 反转链表

移除链表元素

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

文章链接:代码随想录

视频链接:手把手带你学会操作链表 | LeetCode:203.移除链表元素_哔哩哔哩_bilibili

解法:

正常删除链表元素

删除链表元素,需要前一个节点的next指向当前节点的下一个节点即可,即删除节点必须有前驱,这时候就出现了一个情况,如果删除的是头节点怎么办呢?头节点没有前一个节点了,只需要让头节点指针head指向下一个就可以了。
需要考虑两种情况 1.删除的节点为头节点 2.删除的节点不是头节点

有没有一种办法可以统一格式呢,把以上两个情况考虑上去?这个时候就需要借助虚拟头节点了。

public ListNode removeElements(ListNode head, int val) {
    //考虑删除的元素是头节点的情况
    while (head != null && head.val == val) {
        head = head.next;
    }
    if (head == null) return head;
    ListNode pre = head;
    ListNode cur = head.next;
    //删除的元素不是头节点
    while (cur != null) {
        if (cur.val == val) {
            pre.next = cur.next;
        } else {
            pre = cur;
        }
        cur = cur.next;
    }
    return head;
}
虚拟头节点删除元素

设置了虚拟头节点,此时头节点也有了前一个结点,可以把删除的节点为头节点也归为正常删除元素方法中去,这样子就可以使用和移除链表其他节点的方式统一了。

注意点:return dummy.next而不是 return head,因为此时head可能已经被删除了

public ListNode removeElements(ListNode head, int val) {
    if (head == null) return head;
    ListNode dummy = new ListNode(-1, head);
    ListNode pre = dummy;
    ListNode cur = head;
    while (cur != null) {
        if (cur.val == val) {
            pre.next = cur.next;
        } else {
            pre = cur;
        }
        cur = cur.next;
    }
    return dummy.next;
}

设计链表

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

文章链接:代码随想录

视频链接:帮你把链表操作学个通透!LeetCode:707.设计链表_哔哩哔哩_bilibili

解法:

class ListNode {
    int val;
    ListNode next;
    ListNode (int val) {
        this.val = val;
    }
}

class MyLinkedList {
    int size = 0;
    ListNode dummy;

    public MyLinkedList() {
        size = 0;
        dummy = new ListNode(0);
    }
    
    public int get(int index) {
        if (index < 0 || index >= size) return -1;
        ListNode cur = dummy;
        for (int i = 0; i <= index; i++) {
            cur = cur.next;
        }
        return cur.val;
    }
    
    public void addAtHead(int val) {
        addAtIndex(0, val);
    }
    
    public void addAtTail(int val) {
        addAtIndex(size, val);
    }
    
    public void addAtIndex(int index, int val) {
        //考虑没有节点的情况下插入节点
        if (index > size) return;
        if (index < 0) index = 0;
        size++;
        ListNode pre = dummy;
        for (int i = 0; i < index; i++) {
            pre = pre.next;
        }
        ListNode toadd = new ListNode(val);
        toadd.next = pre.next;
        pre.next = toadd;
    }
    
    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) return;
        size--;
        ListNode head = dummy.next;
        ListNode cur = head;
        ListNode pre = dummy;
        for (int i = 0; i < index; i++) {
            pre = cur;
            cur = cur.next;
        }
        pre.next = cur.next;
    }
}

翻转链表

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

文章链接:代码随想录

视频链接:帮你拿下反转链表 | LeetCode:206.反转链表 | 双指针法 | 递归法_哔哩哔哩_bilibili

解法:

双指针写法:

pre:指向前一个节点
cur:指向当前节点
temp:指向后一个节点

public ListNode reverseList(ListNode head) {
    if (head == null) return null;
    ListNode pre = null;	
    ListNode cur = head;	
    ListNode temp = null;	
    while (cur != null) {
        temp = cur.next;
        cur.next = pre;
        pre = cur;
        cur = temp;
    }
    return pre;
}
递归写法:

参照双指针写法来写

public ListNode reverse(ListNode cur, ListNode pre) {
    if (cur == null) return pre;
    ListNode temp = cur.next;
    cur.next = pre;
    return reverse(temp, cur);
}	
public ListNode reverseList(ListNode head) {
    return reverse(head, null);
}

感悟总结

算是复习了链表的删除和增添操作,删除操作需要前驱节点,为了让头节点和其他节点的删除方式一致,便于操作,添加了虚拟头节点,这是一个很常用的方法,但是需要注意的是,在遍历的情况下,节点数不是n,而是n+1,今天是第三天,加油坚持!

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值