文章目录
每日任务
一,滑动窗口理解
二,leetcode 203 移除链表元素
三,leetcode 703 设计链表
四,leetcode 206 反转链表
一、链表基础知识
1、什么是链表
链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域,一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。链表的入口节点称为链表的头结点也就是head。
2、链表的类型
(1)单链表
(2)双链表
(3)循环链表
3、链表的存储方式
链表在内存中可不是连续分布的。链表是通过指针域的指针链接在内存中各个节点。所以链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。
4、链表的操作
二、leetcode 203 (移除链表元素)
1、原题链接
2、解题思路及代码展示
本题首先第一个考虑的问题是,删除节点时,是将整个链表中所有满足条件的节点都删除掉,也就是使用while进行循环,直到链表中再也没有符合条件的节点。
(1)删除非头节点
(2)删除头节点
① 直接在原来的链表中进行删除
移除头结点和移除其他节点的操作是不一样的,因为链表的其他节点都是通过前一个节点来移除当前节点,而头结点没有前一个节点。所以头结点如何移除呢,其实只要将头结点向后移动一位就可以,这样就从链表中移除了一个头结点。
缺点:我对于“头节点”和“非头节点”的处理逻辑需要分开,要针对头节点的删除单独写一个逻辑,比较繁琐,所有就提出了下面的方法,虚拟头节点。
② 增加一个虚拟头节点
给链表添加一个虚拟头结点为新的头结点,此时要移除这个旧头结点元素1。这样是不是就可以使用和移除链表其他节点的方式统一
需要注意的是,return 头结点的时候,返回的是 dummyNode->next;, 这才是新的头结点
/**
* 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 dummyHead = new ListNode();
// 将虚拟头节点指向原始链表的头节点
dummyHead.next = head;
// 定义一个cur,记录当前节点
ListNode cur = dummyHead;
// 执行
while(cur.next != null){
if(cur.next.val == val){
cur.next = cur.next.next;
}else{
cur = cur.next;
}
}
// 注意返回真实的头节点(dummyHead.next)
return dummyHead.next;
}
}
三、leetcode 703 (设计链表)
1、原题链接
2、解题思路及代码展示
直接沿用虚拟头节点的思路,本题要实现五个方法:
(1)获取链表第index个节点的数值
(2)在链表的最前面插入一个节点
(3)在链表的最后面插入一个节点
(4)在链表第index个节点前面插入一个节点
(5)删除链表的第index个节点
直接上代码:
class MyLinkedList {
//size存储链表元素的个数
int size;
//虚拟头结点
ListNode head;
//初始化链表
public MyLinkedList() {
size = 0;
head = new ListNode(0);
}
//获取第index个节点的数值
public int get(int index) {
//如果index非法,返回-1
if (index < 0 || index >= size) {
return -1;
}
ListNode currentNode = head;
//包含一个虚拟头节点,所以查找第 index+1 个节点
for (int i = 0; i <= index; i++) {
currentNode = currentNode.next;
}
return currentNode.val;
}
//在链表最前面插入一个节点
public void addAtHead(int val) {
addAtIndex(0, val);
}
//在链表的最后插入一个节点
public void addAtTail(int val) {
addAtIndex(size, val);
}
// 在第 index 个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
// 如果 index 等于链表的长度,则说明是新插入的节点为链表的尾结点
// 如果 index 大于链表的长度,则返回空
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;
}
//删除第index个节点
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
size--;
ListNode pred = head;
for (int i = 0; i < index; i++) {
pred = pred.next;
}
pred.next = pred.next.next;
}
}
四、leetcode 206 (反转链表)
1、原题链接
2、解题思路及代码展示
(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 reverseList(ListNode head) {
// 定义一个cur指向头节点
ListNode cur = head;
// 定义一个pre指针指向head前的,为null
ListNode pre = null;
// 定义一个temp临时节点,用来存cur的下一个元素,让循环继续下去
ListNode temp = null;
while(cur != null){
// 具体反转操作
temp = cur.next;
cur.next = pre;
// pre 和 cur 统统向后移动,pre到原来cur的位置,cur走到pre的位置
pre = cur;
cur = temp;
}
return pre;
}
}
(2)递归法
结题思路和双指针法是一样的
/**
* 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) {
// // 定义一个cur指向头节点
// ListNode cur = head;
// // 定义一个pre指针指向head前的,为null
// ListNode pre = null;
// // 定义一个temp临时节点,用来存cur的下一个元素,让循环继续下去
// ListNode temp = null;
// while(cur != null){
// temp = cur.next;
// cur.next = pre;
// pre = cur;
// cur = temp;
// }
// return pre;
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);
}
}
总结
提示:这里对文章进行总结: