代码随想录训练营 Day03- 链表(上)

简介: 代码随想录训练营 Day03- 链表(上)

链表


概念


链表通过指针将一组零散的内存块串联在一起。其中,我们把内存块称为链表的“结点”。为了将所有的结点串起来,每个链表的结点除了存储数据之外,还需要记录链上的下一个结点的地址。


分类


单链表


链表通过指针将一组零散的内存块串联在一起。其中,内存块称为链表的“结点”。为了将所有的结点串起来,每个链表的结点除了存储数据之外,还需要记录链上的下一个结点的地址。


双链表


双向链表需要额外的两个空间来存储后继结点和前驱结点的地址。双向链表可以支持 O(1) 时间复杂度的情况下找到前驱结点。


循环链表


循环链表的尾结点指针是指向链表的头结点。


特点


  • 链表查找、插入和删除操作只需要改变 next 指针的指向,O(1)的时间复杂度。
  • 链表随机访问的性能没有数组好,需要 O(n) 的时间复杂度。
  • 内存空间占用不要求连续


作业题


203. 移除链表元素

  • 直接编辑法
package jjn.carl.linkedlist;
import commons.LinkedListHelper;
import commons.ListNode;
import java.lang.management.ThreadInfo;
import java.util.List;
/**
 * @author Jiang Jining
 * @since 2023-06-30 21:51
 */
public class LeetCode203_WithoutDummy {
    public ListNode removeElements(ListNode head, int val) {
        if (head == null) {
            return null;
        }
        // 从头开始,去除全部目标等于val的节点
        while (head != null) {
            if (head.val == val) {
                head = head.next;
            } else {
                break;
            }
        }
        ListNode start = head;
        while (start != null && start.next != null) {
            if (start.next.val == val) {
                start.next = start.next.next;
            } else {
                start = start.next;
            }
        }
        return head;
    }
    public static void main(String[] args) {
        ListNode listNode = LinkedListHelper.buildLinkedList(List.of(6, 6, 6, 6, 6));
        ListNode node = new LeetCode203_WithoutDummy().removeElements(listNode, 6);
        while (node != null) {
            System.out.println("node.val = " + node.val);
            node = node.next;
        }
    }
}


  • 头结点法
package jjn.carl.linkedlist;
import commons.LinkedListHelper;
import commons.ListNode;
import java.util.List;
/**
 * @author Jiang Jining
 * @since 2023-06-30 21:51
 */
public class LeetCode203 {
    public ListNode removeElements(ListNode head, int val) {
        // 添加虚拟头结点,让遍历条件统一
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode start = dummy;
        while (start.next != null) {
            if (start.next.val == val) {
                start.next = start.next.next;
            } else {
                start = start.next;
            }
        }
        return dummy.next;
    }
    public static void main(String[] args) {
        ListNode listNode = LinkedListHelper.buildLinkedList(List.of(6,2,3,4,5,6,7));
        ListNode node = new LeetCode203().removeElements(listNode, 6);
        while (node != null) {
            System.out.println("node.val = " + node.val);
            node = node.next;
        }
    }
}


707. 设计链表

这一题边界条件也太难搞了。

class MyLinkedList {
    class Node {
        int val;
        Node next;
        public Node(int val) {
            this.val = val;
        }
    }
    private final Node dummy;
    private int size;
    public MyLinkedList() {
         dummy = new Node(0);
        size = 0;
    }
     public int get(int index) {
        Node start = dummy;
          if (index < 0 || index > size - 1) {
            return -1;
        }
        while (index >= 0) {
            start = start.next;
            index--;
        }
        return start.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 < 0 || index > size) {
            return;
        }
        Node start = dummy;
        while (index > 0) {
            start = start.next;
            index--;
        }
        Node next = new Node(val);
        next.next = start.next;
        start.next = next;
        size++;
    }
    public void deleteAtIndex(int index) {
       if (index >= size) {
            return;
        }
        Node start = dummy;
        while (index > 0) {
            start = start.next;
            index--;
        }
        start.next = start.next.next;
        size--;
    }
}
/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList obj = new MyLinkedList();
 * int param_1 = obj.get(index);
 * obj.addAtHead(val);
 * obj.addAtTail(val);
 * obj.addAtIndex(index,val);
 * obj.deleteAtIndex(index);
 */


206. 反转链表

遍历法

    public ListNode reverseList(ListNode head) {
        ListNode current = head, previous = null;
        while (current != null) {
            // 必须使用temp存储一下current的下一个节点,防止找不到
            ListNode temp = current.next;
            // 当前节点指向掉头
            current.next = previous;
            // 移动前一个节点
            previous = current;
            current = temp;
        }
        return previous;
    }


递归法

   public ListNode reverseList(ListNode head) {
        return reverse(head, null);
    }
    private ListNode reverse(ListNode current, ListNode pre) {
        if (current == null) {
            return pre;
        }
        ListNode temp = current.next;
        current.next = pre;
        return reverse(temp, current);
    }

目录
相关文章
|
6月前
|
存储 编译器 C语言
【数据结构】C语言实现带头双向循环链表万字详解(附完整运行代码)
【数据结构】C语言实现带头双向循环链表万字详解(附完整运行代码)
53 0
【数据结构】数组、双链表代码实现
【数据结构】数组、双链表代码实现
|
2月前
|
存储 算法 C语言
C语言手撕实战代码_循环单链表和循环双链表
本文档详细介绍了用C语言实现循环单链表和循环双链表的相关算法。包括循环单链表的建立、逆转、左移、拆分及合并等操作;以及双链表的建立、遍历、排序和循环双链表的重组。通过具体示例和代码片段,展示了每种算法的实现思路与步骤,帮助读者深入理解并掌握这些数据结构的基本操作方法。
|
5月前
|
存储 算法
【单向链表】数据结构——单向链表的介绍与代码实现&笔记
【单向链表】数据结构——单向链表的介绍与代码实现&笔记
|
6月前
leetcode代码记录(移除链表元素
leetcode代码记录(移除链表元素
28 0
|
6月前
|
存储
链表的实现(文末附完整代码)
链表的实现(文末附完整代码)
48 2
|
6月前
|
存储
数据结构基础:一篇文章教你单链表(头插,尾插,查找,头删等的解析和代码)
数据结构基础:一篇文章教你单链表(头插,尾插,查找,头删等的解析和代码)
|
5月前
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
|
5月前
|
存储 SQL 算法
LeetCode 题目 86:分隔链表
LeetCode 题目 86:分隔链表
|
5月前
|
存储 算法 Java
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
43 2