每天一道算法题系列十八之删除链表的倒数第N个节点

9 篇文章 0 订阅
8 篇文章 0 订阅

每天一道算法题系列:
来源:力扣(LeetCode)
本题链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
来源是力扣,大家喜欢可以去力扣中文网做相应的其他的题,某浏览器直接搜力扣即可。
本题难度是中等

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

package com.example.likou.likou6;

import static jdk.nashorn.internal.objects.Global.print;

public class NodeTest {

    Node head = null;

    static class Node {
        Node next;
        int val;

        Node() {
        }

        Node(int val) {
            this.val = val;
        }

        Node(int val, Node next) {
            this.val = val;
            this.next = next;
        }
    }

    public static void main(String[] args) {
        NodeTest node1 = new NodeTest();
        node1.addNode(1);
       /* node1.addNode(2);
        node1.addNode(3);
        node1.addNode(4);
        node1.addNode(5);*/

      //  node1.removeNode(3);
        //  node1.delete(3);
      //  node1.reNode(3);
        Node node = new Node();

        node1.removeNthFromEnd(node,1);

    }

    /**
     * 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
     *
     * 示例:
     *
     * 给定一个链表: 1->2->3->4->5, 和 n = 2.
     *
     * 当删除了倒数第二个节点后,链表变为 1->2->3->5.
     * 说明:
     *
     * 给定的 n 保证是有效的。
     *
     * @param node
     * @param i
     */
    /*
    由于我们需要找到倒数第 m 个节点,因此我们可以使用两个指针 first
    和second 同时对链表进行遍历,并且 first 比
     second 超前 m 个节点。当 first 遍历到链表的末尾时,
     second 就恰好处于倒数第 m 个节点。
        这个解释很恰当了
        比如我是
        1 2 3 4 5 
        我要去掉到处第二个 ,也就是4 使其变成1 2 3 5
        首先我们先拿出 1 2 3 4 5 做一个next的操作,next倒数第二次的2
        变成了3 4 5 留着备用,像炒菜一样(我们称为a)
        然后在取一个新的 1 2 3 4 5(我们称为b) 
        然后3 4 5 依次往后面next 等到next为空的时候,相当于进行了三次循环
        所以我们的新的1 2 3 4 5 也进行3次循环 变成了 4 5 
        然后我们直接把next.next的值赋给.next 
        相当于就把4给删除了
        因为第一次循环的a,已经比第二次的循环的b多走了2个数
        等a.next到最后的时候,b还差2个next,所以b的下一个next就是要取代的数
     */
    private void removeNthFromEnd(Node node,int i) {
        /*这里主要是为了防止node为1个数的情况,然后一个数去掉一个数之后后面的代码会
        报空指针异常
         */
        Node node2 = new Node(0,head);
        //因为我这里的题和力扣上面的参数有点差异,所以我就定义的node
        node = node2 ;
        Node node1 = head;
        //这里主要是比最开始出发多i的值
        for (int j = 0; j < i; j++) {
            node1 = node1.next;
        }
        while(node1 != null){
           node1 = node1.next;
           node = node.next;
        }
            node.next = node.next.next;
        //这里主要是进行一个辅助的操作
            Node node3 = node2.next;
//            printList(node2);
        //这里主要进行一个打印的操作
            printList(node3);

    }

    private void printList(Node node2) {
        if(node2 == null){
            System.out.println("");
        }
        //System.out.println(node2.val +"");
        while (node2 != null ){
            System.out.println(node2.val +"");
            node2 = node2.next;
        }
    }

    private Node reNode(int n) {
        Node dummy = new Node(0, head);
        Node first = head;
        Node 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;
        Node ans = dummy.next;
        return ans;

    }

    //删除节点
    public void delete(int no) {
        Node temp = head;
        boolean flag = false;//标识是否找到待删除节点
        while (true) {
            if (temp.next == null) {//已经遍历到最后
                break;
            }
            if (temp.next.val == no) {//找到要删除的节点的前一个节点
                flag = true;//标识
                break;
            }
            temp = temp.next;//temp后移
        }
        if (flag) {//找到节点
            //可以删除
            temp.next = temp.next.next;
        } else {
            System.out.println("要删除的节点" + no + "不存在");
        }
    }


    private void removeNode(int i) {
        if (head == null) {
            return;
        }
        Node pre = head;
        Node cur = pre.next;
        int x = 1;
        while (cur != null) {
            if (i == x) {
                pre.next = cur.next;
                return;
            }
            x++;
            pre = cur;
            cur = cur.next;

        }
    }

    private void addNode(int i) {
        Node pre = new Node(i);
        if (head == null) {
            head = pre;
            return;
        }
        Node node = head;
        while (node.next != null) {
            node = node.next;
        }
        node.next = pre;


    }

    ;


}

上一篇文章:每天一道算法题系列十七之电话号码的字母组合
请继续关注我,如果后面不忙了,会写一系列关于的设计模式等等等的文章。
如果本篇内容有问题,请第一时间联系我,我会第一时间修改。
谢谢大家。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值