代码随想录训练营第三天|203. 移除链表元素、707. 设计链表、206. 翻转链表

文章介绍了LeetCode上的三个链表相关问题:203题移除链表元素,通过设置哑结点简化处理;707题设计链表,实现链表的构造和操作;206题翻转链表,提供两种不同的解法。文章提供了正确的Java代码示例以及错误代码分析,强调了处理链表时的注意事项和技巧。
摘要由CSDN通过智能技术生成

LeetCode 203 移除链表元素
题目链接:移除链表元素

思路:之前处理数组的移除元素需要双指针对原数组内容进行覆盖,但链表的处理方式并不需要这么麻烦。相比之下,链表的移除元素关注点在于头结点的处理,链表结构的定义。

正确思路:下面给出的java代码给出了问题的正确答案,通过设置哑结点作为数值节点的虚拟头结点进行遍历,可以更好的处理头结点本身就是要找的目标值。此外,代码还给出了链表的构造情况。

package ListNode;

/**
 * @author rpstart
 * @create 2023-06-30 19:02
 */
public class removeElements203 {
    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        ListNode node1 = new ListNode(2);
        ListNode node2 = new ListNode(6);
        ListNode node3 = new ListNode(3);
        ListNode node4 = new ListNode(4);
        ListNode node5 = new ListNode(5);
        ListNode node6 = new ListNode(6);
        head.next = node1;
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node6;
        ListNode res = removeElements(head, 6);
        System.out.println(res);
    }

    public static ListNode removeElements(ListNode head, int val) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode cur = dummy;
        while (cur.next != null) {
            if (cur.next.val == val) {
                    cur.next =  cur.next.next;
            }else {
                cur = cur.next;
            }
        }
        return dummy.next;
    }
}

class ListNode {
    int val;
    ListNode next;

    public ListNode() {

    }

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

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

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

易错点:特别注意在处理链表中的循环内部判断时,当找到目标值时,由于已经把目标节点的子节点传给当前节点,所以无需移动指针。只有找不到目标值时才需要移动指针。如果条件判断写错,会出现空指针异常,因为指针跳过了目标节点的子节点。

如下是错误代码,可进行debug查看错误情况。

package ListNode;

/**
 * @author rpstart
 * @create 2023-06-30 19:02
 */
public class removeElements203 {
    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        ListNode node1 = new ListNode(2);
        ListNode node2 = new ListNode(6);
        ListNode node3 = new ListNode(3);
        ListNode node4 = new ListNode(4);
        ListNode node5 = new ListNode(5);
        ListNode node6 = new ListNode(6);
        head.next = node1;
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node6;
        ListNode res = removeElements(head, 6);
        System.out.println(res);
    }

    public static ListNode removeElements(ListNode head, int val) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode cur = dummy;
        while (cur.next != null) {
            if (cur.next.val == val) {
                    cur.next =  cur.next.next;
            }
                cur = cur.next;
            
        }
        return dummy.next;
    }
}

class ListNode {
    int val;
    ListNode next;

    public ListNode() {

    }

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

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

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

LeetCode 707 设计链表
题目链接:设计链表

思路:本题目主要考察对链表的理解,实际上是链表结构的构造器及相应方法的具体实现。链表节点的构造在移除链表元素中已经说明,不再赘述,本题在链表节点结构上进行设计,实现的是链表的构造。

注意,该题在力扣中有些难以理解,因为题目本身的描述不太让初学者看懂,但练习习题者只要懂其中的思路即可。
因为本身题目的链表中,自带一个哑结点,哑结点的下标为0,但不算做数值节点,数值节点的第一个的下标为0,因此每个方法的下标都指的是数值节点。

package ListNode;

import com.sun.org.apache.bcel.internal.generic.NEW;

/**
 * @author rpstart
 * @create 2023-06-30 20:00
 */
public class MyLinkedList707 {

    //链表元素的个数
    int size;
    //头结点
    ListNode head;

    public MyLinkedList707() {
        size = 0;
        //题目要求,节点下标从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;
        }
        if (index < 0) {
            index = 0;
        }
        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--;
        if (index == 0) {
            head = head.next;
            return;
        }
        ListNode cur = head;
        for (int i = 0; i < index; i++) {
            cur = cur.next;
        }
        cur.next = cur.next.next;
    }
}

LeetCode 206 翻转链表

题目链接:翻转链表

思路:翻转链表的思路其实很简单,而且有多种思路,我最常用的还是利用哑结点,因为本身容易理解。需要注意的是由于头插法会使用原链表的当前节点,一定注意不要被覆盖掉,如下代码第一种方式会重新生成节点,第二种方式更优一点。

package ListNode;

/**
 * @author rpstart
 * @create 2023-06-30 20:53
 */
public class reverseList206 {

    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        ListNode node1 = new ListNode(2);
        ListNode node2 = new ListNode(3);
        ListNode node3 = new ListNode(4);
        ListNode node4 = new ListNode(5);
        head.next = node1;
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        ListNode res = reverseList(head);
        System.out.println(res);
    }
    public static ListNode reverseList(ListNode head) {
        ListNode dummy = new ListNode(-1);
        ListNode cur = head;
        while (cur != null) {
            ListNode temp = new ListNode(cur.val);
            temp.next = dummy.next;
            dummy.next = temp;
            cur = cur.next;
        }
        return dummy.next;
    }
}

package ListNode;

/**
 * @author rpstart
 * @create 2023-06-30 20:53
 */
public class reverseList206 {

    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        ListNode node1 = new ListNode(2);
        ListNode node2 = new ListNode(3);
        ListNode node3 = new ListNode(4);
        ListNode node4 = new ListNode(5);
        head.next = node1;
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        ListNode res = reverseList(head);
        System.out.println(res);
    }
    public static ListNode reverseList(ListNode head) {
        ListNode dummy = new ListNode(-1);
        ListNode cur = head;
        while (cur != null) {
            ListNode temp = cur.next;
            cur.next = dummy.next;
            dummy.next = cur;
            cur = temp;
        }
        return dummy.next;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值