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

文章介绍了如何在链表中移除特定值的元素,利用虚拟头节点优化操作,时间复杂度为O(n),空间复杂度为O(1)。同时,还讨论了双指针法和递归法来反转链表,展示了链表操作的两种常见方法。
摘要由CSDN通过智能技术生成

203.移除链表元素

建议: 本题最关键是要理解 虚拟头结点的使用技巧,这个对链表题目很重要。

题目链接/文章讲解/视频讲解::https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.html

以下是用虚拟节点dummy的版本,

  • 时间复杂度 O(n)
  • 空间复杂度 O(1)
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        //链表没东西时候返回链表
        if(head==null){return head;}      
        ListNode dummy=new ListNode(-1,head);
        // cur和pre都是指针
        ListNode pre=dummy;
        ListNode cur=head;
        //while里面用cur或者pre.next都可以
        while(cur!=null){
            if(cur.val==val){
                pre.next=cur.next;
            }else{
                pre=cur;
            }
            cur=cur.next;
        }
        return dummy.next;


    }
}


707这道题目设计链表的五个接口:

获取链表第index个节点的数值
在链表的最前面插入一个节点
在链表的最后面插入一个节点
在链表第index个节点前面插入一个节点
删除链表的第index个节点
可以说这五个接口,已经覆盖了链表的常见操作,是练习链表操作非常好的一道题目

链表操作的方式:
设置一个虚拟头结点在进行操作。

public class MyLinkedList {

    // Definition of the linked list node class
    private class ListNode {
        int val;
        ListNode next;

        // Node constructor
        ListNode(int val) {
            this.val = val;
            this.next = null;
        }
    }

    private int size;
    private ListNode dummyHead;

    // Constructor initializes the linked list
    public MyLinkedList() {
        this.dummyHead = new ListNode(0); // Dummy head node
        this.size = 0;
    }

    // Get the value of the index-th node in the linked list
    public int get(int index) {
        if (index < 0 || index >= this.size) {
            return -1;
        }
        ListNode cur = this.dummyHead.next;
        while (index > 0) {
            cur = cur.next;
            index--;
        }
        return cur.val;
    }

    // Add a node at the head of the linked list
    public void addAtHead(int val) {
        addAtIndex(0, val);
    }

    // Append a node at the tail of the linked list
    public void addAtTail(int val) {
        addAtIndex(this.size, val);
    }

    // Add a node with value `val` before the index-th node in the linked list
    public void addAtIndex(int index, int val) {
        if (index > this.size) {
            return;
        }
        if (index < 0) {
            index = 0;
        }
        this.size++;
        ListNode pred = this.dummyHead;
        for (int i = 0; i < index; i++) {
            pred = pred.next;
        }
        ListNode newNode = new ListNode(val);
        newNode.next = pred.next;
        pred.next = newNode;
    }

    // Delete the index-th node in the linked list, if the index is valid
    public void deleteAtIndex(int index) {
        if (index < 0 || index >= this.size) {
            return;
        }
        this.size--;
        ListNode pred = this.dummyHead;
        for (int i = 0; i < index; i++) {
            pred = pred.next;
        }
        pred.next = pred.next.next;
    }

    // Print the linked list
    public void printLinkedList() {
        ListNode cur = this.dummyHead;
        while (cur.next != null) {
            System.out.print(cur.next.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }
}


206.反转链表

双指针:
时间复杂度: O(n)
空间复杂度: O(1)
动图看https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
 //双指针法
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre=null;//这是双链表的头节点的前指针
        ListNode cur=head;//这是双链表的头节点的现指针
        ListNode temp=null;
        while(cur!=null){//当cur指到null时候,pre也到了最后一个节点
            temp=cur.next;
            cur.next=pre;
            //pre和cur都继续往后走了;
            pre=cur;
            cur=temp;
        }
        return pre;

    }
}

递归法,是基于双指针基础上的。
时间复杂度: O(n), 要递归处理链表的每个节点
空间复杂度: O(n), 递归调用了 n 层栈空间

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
 //递归法
class Solution {
    public ListNode reverseList(ListNode head) {
        return reverse(null,head);}

    private ListNode reverse(ListNode pre,ListNode cur){
        if(cur==null){
            return pre;
        }
        ListNode temp=null;
        temp=cur.next;//保存下一个节点
        cur.next=pre;//然后反转
        return reverse(cur,temp);//然后往后递归,这时候前驱节点和后继节点都右移了一位。

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值