day5_链表基础知识和leetcode203.移除链表元素

day5_链表基础知识

0、基础理论

来自代码随想录总结

①单链表:每个节点包括数据域(data)和指针域(next),最后一个节点指针域指向null,入口节点为链表的头节点(head)向后查询

②双链表:两个指针域,一个数据域。prev data next。头节点的prev为null,最后一个节点的next为null.向前向后都可以查询

③循环链表:链表首尾相连。即把单链表的最后一个节点从指向null改为指向头节点

④存储方式:链表在内存中不是连续分布的(头节点和第二个节点可能不相连)。通过指针域的指针链接内存中的各个节点。分配机制取决于操作系统的内存管理。

⑤链表定义!!:

public 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;
    }
}

⑥链表操作

删除i节点:让i-1节点的指针域指向i+1节点即可。C++要手动释放i节点,但Java Python有内存回收机制,不用手动释放。

在i节点后面添加k节点:让i节点的指针指向从i+1变到k,k的指针指向i+1。

链表增删都是O(1),但是链表查找时间复杂度是O(n)

⑦性能分析
与数组的区别

1、203.移除链表元素

leetcode203

题意:删除链表中等于给定值 val 的所有节点。

示例 1: 输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]

示例 2: 输入:head = [], val = 1 输出:[]

示例 3: 输入:head = [7,7,7,7], val = 7 输出:[]

三种方法实现

单链表

/**
 * 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; }
 * }
 */
//时间复杂度 O(n)
//空间复杂度 O(1)
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        // 不能用if. if只判断一次,这里要用whlile一直判断直到头节点不是val
        while(head != null && head.val == val){
            head = head.next;
        }
        ListNode curr = head;  //curr临时指针 判断
        // 链表存在并且不是最后一个节点。
        // 如果是最后一个节点 就直接退出。当前节点是否满足条件由上一节点判断的。所以最后一个节点已经由倒数第二个节点判断了
        //要操作curr.next所以要判断curr不为空
        while(curr != null && curr.next != null){
            if(curr.next.val == val){
                curr.next = curr.next.next;
            }else{
                curr = curr.next;
            }
        }
        return head;
        
    }
}

双链表

//时间复杂度 O(n)
//空间复杂度 O(1)
public ListNode removeElements(ListNode head, int val) {
    while (head != null && head.val == val) {
        head = head.next;
    }
    // 已经为null,提前退出
    if (head == null) {
        return head;
    }
    // 已确定当前head.val != val
    ListNode pre = head;
    ListNode cur = head.next;
    while (cur != null) {
        if (cur.val == val) {
            //让i-1节点的指针域指向i+1节点即可跳过i节点
            pre.next = cur.next;
        } else {
            pre = cur;
        }
        cur = cur.next;
    }
    return head;
}

虚拟头节点

//时间复杂度 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) {
        // 新建链表 带有一个指向头节点指针的虚拟头节点
        ListNode dummy = new ListNode();
        dummy.next = head;

        ListNode curr = dummy;
        // 链表不是最后一个节点。
        // 如果是最后一个节点 就直接退出。当前节点是否满足条件由上一节点判断的。所以最后一个节点已经由倒数第二个节点判断了
        //只用这个判断条件就行
        while(curr.next != null){
            if(curr.next.val == val){
                curr.next = curr.next.next;
            }else{
                curr = curr.next;
            }
        }
        // 不能返回head 可能会被删除了
        return dummy.next;
        
    }
}

你可能感兴趣的:(链表,数据结构,java,leetcode,算法)