删除链表倒数第N个节点

力扣

package Algorithms;

import java.util.List;

/**
 * @author : zhang
 * @version : 1.0
 * @date : Create in 2021/7/31
 * @description :
 */
public class RemoveNthFromEnd {
    public static void main(String[] args) {
        ListNode list1 = new ListNode(1);
        ListNode list2 = new ListNode(2);
        ListNode list3 = new ListNode(3);
        ListNode list4 = new ListNode(4);

        SingleList singleList = new SingleList();
        singleList.add(list1);
        singleList.add(list2);
        singleList.add(list3);
        singleList.add(list4);

        System.out.println("原链表为:");
        singleList.list();
        //删除倒数第2个节点3
        ListNode listNode = removeNthFromEnd_2(singleList.getHead(), 2);
        System.out.println("删除后的链表为:");
        singleList.list();
    }

    //获取单链表节点的个数
    public static int getLength(ListNode head) {
        int length = 0;
        ListNode cur = head;
        while (cur.next != null) {
            length++;
            cur = cur.next;
        }
        return length;
    }

    //删除倒数第N个节点
    //方式1:查找出倒数第N+1个节点
    public static ListNode removeNthFromEnd_1(ListNode head, int n) {
        if (head == null) {
            return null;
        }
        int size = getLength(head);
        if (n <= 0 || n > size){
            return null;
        }
        //for循环定位到倒数第N+1个节点
        // head -> 1 -> 2 -> 3 -> 4   size = 4, cur = head
        // 倒数第N+1个节点需要遍历的次数为:size-N+1 比如:需要删除倒数第N = 2个节点 3 ,
        // 需要找到它的前一个节点2,遍历的次数为4-2=2次,
        ListNode cur = head;
        for (int i = 0; i < size-n; i++) {
            cur = cur.next;
        }
        //退出循环后就找到了倒数第N+1个节点,然后删除倒数第N个节点
        cur.next = cur.next.next;
        return head;
    }

    //删除倒数第N个节点
    //方式2:通过双指针(first、second)的方式进行删除
    //first比second超前n个节点,当first遍历到链表的末尾时,second就恰好是倒数第n个节点
    //1、first 和second指向头结点(这里的头节点不存放任何数据,相当于dummy),首先使用first对链表进行遍历n次
    //2、同时使用first和second对链表进行遍历,当first遍历到链表末尾时,second就恰好是倒数第n个节点
    //注:遍历的时候考虑second指向倒数第N个节点的前一个节点有助于我们删除
    public static ListNode removeNthFromEnd_2(ListNode head, int n) {
        ListNode first = head.next;
        ListNode second = head;
        for (int i = 0; i < n; i++) {
            first = first.next;
        }
        //for循环结束后,first和second之间相隔n个元素,然后对first和second同时进行遍历,
        //当first指向链表末尾时,second指向倒数第n个节点的前驱节点
        while (first != null){
            first = first.next;
            second = second.next;
        }
        second.next = second.next.next;
        return head;

    }
}

//定义SingleList,来管理ListNode
class SingleList {
    //初始化一个头节点,不存放任何数据
    private ListNode head = new ListNode(0);

    public ListNode getHead() {
        return head;
    }

    //添加节点到单向链表中
    public void add(ListNode listNode) {
        ListNode temp = head;
        while (true) {
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        temp.next = listNode;
    }

    //显示单向链表
    public void list() {
        if (head.next == null) {
            System.out.println("链表为空!");
            return;
        }

        ListNode temp = head.next;
        while (true) {
            if (temp == null) {
                break;
            }
            System.out.println(temp);
            temp = temp.next;
        }
    }
}

class ListNode {
    int val;
    ListNode next;

    ListNode() {
    }

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

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

    @Override
    public String toString() {
        return "ListNode{" +
                "val=" + val +
                '}';
    }
}

 

posted @ 2021-07-31 11:39  zh_小猿  阅读(51)  评论(0编辑  收藏  举报