删除链表的倒数第N个节点

题干:给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.

如果没有快慢指针的思想, 我可能就是通过遍历两遍来解决。第一次遍历得到链表的长度,然后第二次遍历到相应的地方,然后进行删除。
在做过了求解链表中间节点及链表是否有环的问题后就会接触到快慢指针,很自然的想到本题也可以用快慢指针的思想解答。

具体代码如下:

fun removeNthFromEnd(head: ListNode?, n: Int): ListNode? {
	// leetcode题目一定要注意参数合法性
    if (head == null) {
        return head
    }
    // 构建一个哑节点,方便处理一些特殊情况,如删除第一个节点。 
    var dummyNode = ListNode(0)
    dummyNode.next = head

	// 定义一个慢指针和一个快指针
    var slow: ListNode? = dummyNode
    var fast: ListNode? = dummyNode

    // 快的先走n步,让快指针与慢指针之间的距离拉开为n。
    // for的取值为[0, n] 左右都是闭区间。(故实际是快慢指针之前的距离是n + 1,这样是因为让slow指向待删除的前一个节点。如果此处的区间不包括n,那么后面遍历完成时slow正好指向待删除元素。)
    for (i in 0..n) {
        fast = fast?.next
    }
    
	// 让快慢指针同时向后遍历,当快指针为空时,慢指针正好指向待删除节点的前一个节点。
    while (fast != null) {
        fast = fast.next
        slow = slow?.next
    }

    // 此时slow是待删除节点的前一个节点
    slow?.next = slow?.next?.next

    return dummyNode.next
}

如此,使用快慢指针则只用遍历一次链表即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值