算法-leetcode-链表问题- 19. 删除链表的倒数第 N 个结点

文章目录

    • 15, `19. 删除链表的倒数第 N 个结点`
      • 思路1: 暴力遍历删除
      • 思路2: 使用栈结构
      • 思路3: 双指针法

15, 19. 删除链表的倒数第 N 个结点

https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/

思路1: 暴力遍历删除

思路2: 使用栈结构

思路3: 双指针法

  • 第一个指针指向第0个节点, 第二个指针指向n个节点,
  • 两个指针同时往有移动,
  • 当第二个指针指向最后一个节点当时候, 第一个指针必定指向倒数第n个节点的前一个节点
package com.shangguigu.dachang.algrithm.A05_linkedList;

import java.util.Stack;

/**
 * @author : 不二
 * @date : 2022/4/11-下午3:59
 * @desc : 19. 删除链表的倒数第 N 个结点
 * https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
 **/
public class A51_removeNthFromEnd {
    public static void main(String[] args) {

        ListNode l1 = new ListNode(1);
        ListNode l2 = new ListNode(2);
        ListNode l3 = new ListNode(3);
        ListNode l4 = new ListNode(4);
        ListNode l5 = new ListNode(5);
        l1.next = l2;
        l2.next = l3;
        l3.next = l4;
        l4.next = l5;

//        ListNode listNode = removeNthFromEnd_by_violance(l1, 1);
//        ListNode listNode = removeNthFromEnd_by_stack(l1, 2);
        ListNode listNode = removeNthFromEnd_by_twoPointer(l1, 2);
        System.out.println("结果是:" + listNode);
    }
    

    /**
     * 思路3:双指针法(一次遍历)
     * 第一个指针指向0, 第二个指针指向n,
     * 两个指针同时往有移动,
     * 当第二个指针指向最后一个节点当时候, 第一个指针必定指向倒数第n个节点的前一个节点
     *
     */
    public static ListNode removeNthFromEnd_by_twoPointer(ListNode head, int n){

        // first先走n步,然后first和second一起走,当first走到最后一个节点的时候,那么second必然指向倒数第n节点的前一个节点
        ListNode first = head;
        ListNode second = head;
        for (int i = 0; i < n; i++) {
            if (i < n - 1 && first.next == null) {
                // 说明n大于链表长度, 没法删除,直接返回头节点即可
                return head;
            } else if (i == n - 1 && first.next == null) {
                // 说明删除的刚好是头节点
                return head.next;
            } else {
                first = first.next;
            }
        }

        // 说明删除的是第一个节点后面的节点
        while (first.next != null) {
            first = first.next;
            second = second.next;
        }
        second.next = second.next.next;
        return head;
    }


    /**
     * 思路2:使用栈结构!!!
     */
    public static ListNode removeNthFromEnd_by_stack(ListNode head, int n){
        Stack<ListNode> stack = new Stack<>();
        ListNode currNode = head;
        int length = 0;
        while (currNode != null) {
            length++;
            stack.push(currNode);
            currNode = currNode.next;
        }

        // 这里默认n不会超过链表的长度哈
        if (n > length) {
            return head;
        } else if (n == length) {
            return head.next;
        } else {
            // 这里要多走一步,找到前一个节点,方便删除指定节点
            for (int i = 0; i <= n-1; i++) {
                stack.pop();
            }
            stack.peek().next = stack.peek().next.next;
            return stack.firstElement();
        }


    }


    /**
     * 思路1:暴力法:直接遍历找出长度,然后再遍历删除
     */
    public static ListNode removeNthFromEnd_by_violance(ListNode head, int n) {

        int length = 0;
        ListNode theNode1 = head;
        while (theNode1 != null) {
            length++;
            theNode1 = theNode1.next;
        }
        // System.out.println("长度是:" + length);

        if (n > length) {
            return head;
        } else if (n == length) {
            head = head.next;
            return head;
        } else {

            ListNode theNode = head;
            ListNode preNode = head;
            for (int i = 0; i < length - n; i++) {
                preNode = theNode;
                theNode = theNode.next;
            }

            // 这里删除指定节点
            preNode.next = theNode.next;
            return head;
        }
    }
}

你可能感兴趣的:(算法,java,算法,leetcode)