给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

本题是LeetCode第19题,以后题目也可能会变。本题的描述如下:

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.

思路:用两个节点,删除让前一个节点比后一个节点先跑n次,然后两个一起跑。当前一个节点遍历结束或者为空的时候,后一个节点是要删除的元素,但是要删除一个元素,必须知道它的前一个节点,其实遍历的时候就不用等到最后一个节点为空,可以在最后一个节点的next域为空的时候结束循环。这样,后一个节点的指向的下一个元素就是要删除的元素,将其删除即可。

代码如下:

public static ListNode removeNthFromEnd(ListNode head, int n) {
        //当链表为空或者要删除的节点小于等于0的时候,直接返回head
        if (head == null || n <= 0)
            return head;
        //建立一个虚拟的表头结点,因为需要删除的节点有可能是头结点,
        // 所以建立虚拟头结点可以不用分是否是头结点两种情况
        ListNode tempHead = new ListNode(0);
        tempHead.next = head;
        ListNode p = tempHead, q = tempHead;
        //p指针比q指针先跑n次
        for (int i = 0; i < n; i++) {
            //如果p为空的时候,说明这个节点的长度不足n,返回head
            if (p == null )
                return head;
            else {
                p = p.next;
            }
        }
        //p,q一起往前跑,直到p的next为空,
        // q所指向的下一个结点就是要删除的元素的位置
        while (p.next != null) {
            p = p.next;
            q = q.next;
        }
        
        //删除q指向的节点的下一个元素
        q.next = q.next.next;
        //删除虚拟头结点
        return tempHead.next;
    }

本题的完整的代码如下:
 

public class Num19 {
    public static void main(String[] args) {
        int[] arr = {3, 2, 5, 8, 4, 7, 6, 9};
        ListNode head = new ListNode(arr);
        head = removeNthFromEnd(head, 8);
        System.out.println(head.toString());
 
    }
 
    public static ListNode removeNthFromEnd(ListNode head, int n) {
        //当链表为空或者要删除的节点小于等于0的时候,直接返回head
        if (head == null || n <= 0)
            return head;
        //建立一个虚拟的表头结点,因为需要删除的节点有可能是头结点,
        // 所以建立虚拟头结点可以不用分是否是头结点两种情况
        ListNode tempHead = new ListNode(0);
        tempHead.next = head;
        ListNode p = tempHead, q = tempHead;
        //p指针比q指针先跑n次
        for (int i = 0; i < n; i++) {
            //如果p为空的时候,说明这个节点的长度不足n,返回head
            if (p == null )
                return head;
            else {
                p = p.next;
            }
        }
        //p,q一起往前跑,直到p的next为空,
        // q所指向的下一个结点就是要删除的元素的位置
        while (p.next != null) {
            p = p.next;
            q = q.next;
        }
 
        //删除q指向的节点的下一个元素
        q.next = q.next.next;
        //删除虚拟头结点
        return tempHead.next;
    }
 
    static class ListNode {
        int val;
        ListNode next;
 
        ListNode(int x) {
            val = x;
        }
 
        public ListNode(int[] arr) {
            if (arr == null || arr.length == 0)
                throw new IllegalArgumentException("arr can to be empty");
            this.val = arr[0];
            ListNode cur = this;
            for (int i = 1; i < arr.length; i++) {
                cur.next = new ListNode(arr[i]);
                cur = cur.next;
            }
        }
 
        @Override
        public String toString() {
            StringBuilder res = new StringBuilder();
            ListNode cur = this;
            while (cur != null) {
                res.append(cur.val + "->");
                cur = cur.next;
            }
            res.append("NULL");
            return res.toString();
        }
    }
}

此函数的LeetCode上面提交正确,无毒无害,可以使用!

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值