Leetcode19题单链表删除倒数结点

写在前面

题目传送门:leetcode链表题

image-20220101185309632

一、自己写的代码

自己的思路是暴力破解的方法,也就是将倒数便为正数,再去匹配,两次循环遍历

当然,自己最后没有实现,因为没有考虑到哑结点,有些测试用例无法通过

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 链表只有一个元素
        if(head == null){
            return null;
        }
        //计算有效的节点数
        int length = 0;
        ListNode temp = head;
        while(temp != null){
            length++;
            temp = temp.next;
        }
        // 转换逻辑
        n = length - n;
        temp = head.next;
        ListNode cur = temp;
        for(int i = 0; i <= n; i++){
            cur = temp;
            // 后移
            temp = temp.next;
            if(i == n - 1){
                cur.next = temp.next;
                temp = cur.next;     
            }

        }
        return head;
    }
}

二、官方解法

在对链表进行操作时,一种常用的技巧是添加一个哑节点(dummy node),它的 next 指针指向链表的头节点。这样一来,我们就不需要对头节点进行特殊的判断了。

例如,在本题中,如果我们要删除节点 y,我们需要知道节点 y 的前驱节点 x,并将 x 的指针指向 y 的后继节点。但由于头节点不存在前驱节点,因此我们需要在删除头节点时进行特殊判断。但如果我们添加了哑节点,那么头节点的前驱节点就是哑节点本身,此时我们就只需要考虑通用的情况即可。

特别地,在某些语言中,由于需要自行对内存进行管理。因此在实际的面试中,对于「是否需要释放被删除节点对应的空间」这一问题,我们需要和面试官进行积极的沟通以达成一致。下面的代码中默认不释放空间。

解法一:计算链表长度

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 哑节点
        ListNode dummpy = new ListNode(0,head);
        // 获取长度
        int length = getLen(head);
        ListNode cur = dummpy;
        for(int i = 0; i < length - n; i++){
            // 后移
            cur = cur.next;
        }
        // 删除操作
        cur.next = cur.next.next;
        // 返回遍历的头结点(除去哑结点)
        ListNode ans = dummpy.next;
        return ans;
    }
	// 获取有效长度
    public int getLen(ListNode head){
        int length = 0;
        while(head != null){
            length++;
            head = head.next;
        }
        return length;
    }
}

解法二:快慢双指针

思路:

1、定义两个指针,然后快指针fast领先慢指针slow n 个节点

2、当快指针遍历到最后时,就可以停止两个指针向下遍历了。然后就可以堆满指针的位置进行删除操作了

自己的写法

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 哑节点
        ListNode dummpy = new ListNode(0,head);
        // 快节点
        ListNode fast = head;
        // 慢节点
        ListNode slow = dummpy;
        while(true){
            if(fast.next == null){
                break;
            }
            // 让快指针领先n个位置
            if(n > 0){
                n--;
            }else{
                // 慢指针后移
                slow = slow.next;
            }
            // 快指针后移
            fast = fast.next;
        }
        // 删除节点
        slow.next = slow.next.next;
        return dummpy.next;
    }
}

官方写法

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0, head);
        ListNode first = head;
        ListNode second = dummy;
        for (int i = 0; i < n; ++i) {
            first = first.next;
        }
        while (first != null) {
            first = first.next;
            second = second.next;
        }
        second.next = second.next.next;
        ListNode ans = dummy.next;
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可爱发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值