代码随想录Day_03|Leetcode.203.707.206(创建链表哑节点,递归翻转链表)

本文介绍了链表中的移除头结点和普通节点操作,创建自定义链表类MyLinkedList的方法,以及如何反转链表的两种方法。重点展示了如何处理边界条件和链表结构的调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

203.链表移除元素

移除头结点和移除其他节点的操作是不一样的,因为链表的其他节点都是通过前一个节点来移除当前节点,而头结点没有前一个节点。

所以头结点如何移除呢,其实只要将头结点向后移动一位就可以,这样就从链表中移除了一个头结点。

class Solution {

    public ListNode removeElements(ListNode head, int val) {
        while (head != null && head.val == val) {
            head = head.next;
        }
        ListNode curr = head;
        while (curr != null) {
            while (curr.next != null && curr.next.val == val) {
                curr.next = curr.next.next;
            }
            curr = curr.next;
        }
        return head;
    }
}

707.创建自己的链表

在初始设置值为0的虚拟头节点,然后在后续都在存在虚拟头节点的情况下操作,学习这个思想。

每一个单独的方法都要首先考虑index小于0和大于size(链表元素个数)的情况,然后再判断正常情况下的操作,这道题需要全面看待,addatHead和addatTail都是addIndex的特殊情况。

class MyLinkedList {
    int size;
    ListNode head;

    public MyLinkedList() {
        size = 0;
        head = new ListNode(0);
    }

    public int get(int index) {
        if (index < 0 || index >= size) {
            return -1;
        }
        ListNode cur = head;
        for (int i = 0; i <= index; i++) {
            cur = cur.next;
        }
        return cur.val;
    }

    public void addAtHead(int val) {
        addAtIndex(0, val);
    }

    public void addAtTail(int val) {
        addAtIndex(size, val);
    }

    public void addAtIndex(int index, int val) {
        if (index > size) {
            return;
        }
        index = Math.max(0, index);
        size++;
        ListNode pred = head;
        for (int i = 0; i < index; i++) {
            pred = pred.next;
        }
        ListNode toAdd = new ListNode(val);
        toAdd.next = pred.next;
        pred.next = toAdd;
    }

    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) {
            return;
        }
        size--;
        ListNode pred = head;
        for (int i = 0; i < index; i++) {
            pred = pred.next;
        }
        pred.next = pred.next.next;
    }
}

class ListNode {
    int val;
    ListNode next;

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

206.反转链表

这道题巩固链表逆置操作,要与数组逆置比较看

自己的啰嗦版:

设立p指针对应当前位置,q指针对应下一个位置,head指针对应上一个位置,按顺序改变指针,记得在开始判断空链表和仅有一个元素的链表的情况。循环结束条件是当前p指针为null。

class Solution {
    public ListNode reverseList(ListNode head) {
        if(head==null||head.next==null)
            return head;
        ListNode p = head.next;
        ListNode q = p.next;
        head.next = null;
        while (p != null) {
            p.next=head;
            head=p;
            p=q;
            if(q!=null)
                q=q.next;
        }
        return head;
    }
}

leetcode简洁版:

每次先记录下一个节点,然后将当前节点指针指向pre,最后移动cur和pre。

class Solution {
        public ListNode reverseList (ListNode head){
            ListNode prev = null;
            ListNode curr = head;
            while (curr != null) {
                ListNode next = curr.next;
                curr.next = prev;
                prev = curr;
                curr = next;
            }
            return prev;
        }

    }

终极简洁版(递归):

红色最深层递归,绿色次深处,黄色最后一层递归。

class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null)
            return head;//找到链表尾部,新的头节点
        ListNode newhead=reverseList(head.next);//递归深入,当找到尾部时,此时head是倒数第二个节点
        head.next.next=head;//将当前的head和head.next指针翻转
        head.next=null;//每一次都将head。next指向null,方便最后的原始头节点指向null
        return newhead;//将找到的newhead每次都传承下去
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值