算法-从单向无环链表中删除倒数第n个节点

从单向无环链表中删除倒数第n个节点

题目

给定一个链表: 1->2->3->4->5, 和 n = 2。删除倒数第“n”个节点后,链表为:1->2->3->5
说明: 给定的 n 保证是有效的。
要求: 只允许对链表进行一次遍历。

分析

题目中的链表是单向链表,这样要删除倒数第n元素,则需要找到倒数n+1个元素,否则将无法删除倒数第n个节点。

  • 如果倒数第n+1个节点存在,删除的核心代码为:parent.next = parent.next.next;

  • 如果倒数第n+1个节点不存在(即倒数第n个节点是链首),则将链首的子节点数据复制到链首即可完成删除链首的操作。

思路

参考判断链中是否有环中" 快慢指针 "的思路,这里用两个步长均为1的指针p1,p2,指针p2比指针p1 先行 n+1 步。p2指针指向尾部时,p1指针刚好指向倒数第n+1个节点。

实现代码如下

public static LinkNode remove(LinkNode head, int n) {
        LinkNode p1 = head;
        LinkNode p2 = head;
        int step = 0;
        //p2先行n+1步,然后将p2移动到链尾的子节点(即null)。
        while (p2 != null) {
            p2 = p2.next;
            //当p2优先p1走了n+1步,则p1开始移动
            if (++step > n + 1) {
                p1 = p1.next;
            }
        }
  
        //step从0开始记步数,且从head节点开始,表示走了step步,由此计算链表长度为step+1,
        //又因为step跳出循环时,指针指向链表外的null,即多走了1步,
        //故,链表的长度等于step+1-1=step。减去的那一步为多走(多计数)的一步。
        if (step < n) {
            System.out.println("链表长度为:"+step+",不够\t" + n);
            return null;
        }

        LinkNode temp;
        //要移除的节点为链表的头节点
        if (head.equals(p1)) {
            //将head数据复制到temp中;
            temp = new LinkNode(head.data);
            //将head子节点的数据复制到head中,完成head数据的移除。
            head.data = head.next.data;
            head.next = head.next.next;
        }else {
            //要移除存在父节点
            temp = p1.next;
            p1.next = p1.next.next;
        }
        return temp;
    }

    public static void main(String[] args) {
        /**
         * 构件链表 1->2->3->4->5
         */
        LinkNode head = new LinkNode(1);
        LinkNode h2 = new LinkNode(2);
        LinkNode h3 = new LinkNode(3);
        LinkNode h4 = new LinkNode(4);
        LinkNode h5 = new LinkNode(5);
        head.next = h2;
        h2.next = h3;
        h3.next = h4;
        h4.next = h5;
        int n = 5;//测试6,5,2,1情况下输出结果
        LinkNode remove = remove(head, n);
        if (remove != null) {
            System.out.println("被移除的倒数第" + n + "个元素是:" + remove.data);
        } else {
            System.out.println("被移除的倒数第" + n + "个元素不存在。");
        }
        System.out.println("移除操作完成后,链表如下:");
        while (head.next != null) {
            System.out.print(head.data + "->");
            head = head.next;
        }
    }

结果:

  • 删除倒数第6个节点,结果如下
链表长度为:5,不够:6
被移除的倒数第6个元素不存在。
移除操作完成后,链表如下:1->2->3->4->5
  • 删除倒数第5个节点,结果如下
被移除的倒数第5个元素是:1
移除操作完成后,链表如下:2->3->4->5
  • 删除倒数第2个节点,结果如下
被移除的倒数第2个元素是:4
移除操作完成后,链表如下:1->2->3->5
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值