算法day03-链表篇(1)

今日任务目录

  1. 链表理论基础
  2. 203.移除链表元素
  3. 707.设计链表
  4. 206.反转链表

  今天这一节是和链表的基础操作相关的,更加复杂的题目我们放到后面由浅入深来做。

一、链表理论基础

二、移除链表元素

  这是力扣203题(),本题最关键是要理解虚拟头节点的使用技巧,这对链表题目很重要。

   主要思路:对于ACM模式,我们要先构建节点。我们可以从head来遍历这条链表,遇到节点值等于val的节点则删除。那么删除节点的操作怎么做呢?

  1) 普通方法对于头节点删除和中间节点的删除操作不一样,头节点只需将指针往下移一个,指向下一个节点,但是中间节点需要指向下下个。

  2)添加一个虚拟头节点。这样整个删除的代码都是以同一的逻辑来删除。

 1 /**  方法一:
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode() {}
 7  *     ListNode(int val) { this.val = val; }
 8  *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 9  * }
10  */
11 class Solution {
12     public ListNode removeElements(ListNode head, int val) {
13         while(head != null && head.val == val){      //持续的过程
14             head = head.next;
15         }   
16         ListNode cur = head;
17         while(cur != null && cur.next != null){     //因为我们要操作cur.next
18             if(cur.next.val == val){            //我们要删除的是cur.next,因为这样能找到它的前一个节点cur
19                 cur.next = cur.next.next;
20             }else{
21                 cur = cur.next;
22             }
23         }
24         return head;
25     }
26 }
//时间复杂度:O(n)
//空间复杂度:O(1)
 1 class Solution {
 2     public ListNode removeElements(ListNode head, int val) {
 3         ListNode dummyHead = new ListNode();        //构建虚拟节点指向头节点
 4         dummyHead.next = head;
 5 
 6         ListNode cur = dummyHead;
 7         while(cur.next != null){
 8             if(cur.next.val == val){
 9                 cur.next = cur.next.next;
10             }else{
11                 cur = cur.next;
12             }
13         }
14         return dummyHead.next;
15     }
16 }

 

三、设计链表

  这是力扣707题(707. 设计链表 - 力扣(LeetCode))。这里涉及到链表的一些基本操作,需要仔细弄懂。

 1 class MyLinkedList {
 2 
 3     // 定义链表节点内部类
 4     class ListNode {
 5         int val;        // 节点值
 6         ListNode next;  // 指向下一个节点的指针
 7 
 8         ListNode(int val) {
 9             this.val = val;
10         }
11     }
12 
13     private int size;         // 当前链表元素数量
14     private ListNode dummyHead; // 虚拟头节点(不存储真实数据,只是为了统一操作)
15 
16     // 初始化链表
17     public MyLinkedList() {
18         this.size = 0;
19         this.dummyHead = new ListNode(0); // 虚拟头节点值可以随意设,比如0
20     }
21 
22     // 获取链表第 index 个节点的值(0-based)
23     public int get(int index) {
24         // 如果索引非法,返回 -1
25         if (index < 0 || index >= size) {
26             return -1;
27         }
28         // 从 dummyHead 后的第一个节点开始走
29         ListNode cur = dummyHead.next;
30         while (index > 0) {
31             cur = cur.next;
32             index--;
33         }
34         return cur.val;
35     }
36 
37     // 在链表头部添加一个节点
38     public void addAtHead(int val) {
39         ListNode newNode = new ListNode(val);
40         newNode.next = dummyHead.next;
41         dummyHead.next = newNode;
42         size++;
43     }
44 
45     // 在链表尾部添加一个节点
46     public void addAtTail(int val) {
47         ListNode newNode = new ListNode(val);
48         ListNode cur = dummyHead;
49         // 找到最后一个节点
50         while (cur.next != null) {
51             cur = cur.next;
52         }
53         cur.next = newNode;
54         size++;
55     }
56 
57     // 在链表指定位置 index 前插入一个节点
58     public void addAtIndex(int index, int val) {
59         // 如果 index > size,无法插入
60         if (index > size) {
61             return;
62         }
63         // 如果 index 小于0,按照在头部插入处理
64         if (index < 0) {
65             index = 0;
66         }
67 
68         ListNode newNode = new ListNode(val);
69         ListNode cur = dummyHead;
70         // 找到第 index 个节点的前一个节点
71         while (index > 0) {
72             cur = cur.next;
73             index--;
74         }
75         newNode.next = cur.next;
76         cur.next = newNode;
77         size++;
78     }
79 
80     // 删除链表中第 index 个节点
81     public void deleteAtIndex(int index) {
82         // 索引非法,直接返回
83         if (index < 0 || index >= size) {
84             return;
85         }
86         ListNode cur = dummyHead;
87         // 找到要删除节点的前一个节点
88         while (index > 0) {
89             cur = cur.next;
90             index--;
91         }
92         // 删除操作:让前一个节点跳过要删除的节点
93         cur.next = cur.next.next;
94         size--;
95     }
96 }

 【相关题目】

  • LRU

四、反转链表

  这是力扣206题(206. 反转链表 - 力扣(LeetCode)),这里有很多反转链表需要注意的点。

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode() {}
 7  *     ListNode(int val) { this.val = val; }
 8  *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 9  * }
10  */
11 class Solution {
12     public ListNode reverseList(ListNode head) {
13         ListNode cur = head, pre = null;
14         while(cur != null){     //尾节点的next为null
15             ListNode nxt = cur.next;
16             cur.next = pre; 
17             pre = cur;
18             cur = nxt;
19         }
20         return pre;
21     }
22 }
//时间复杂度:O(N),遍历了每个节点
//空间复杂度:O(1),只用了常量级指针

【相关题目】

  • k个一组反转链表
  •  

 

posted @ 2025-04-25 17:30  筱倩  阅读(322)  评论(0)    收藏  举报