详细解析 | 请看Carl老师讲解
链表理论基础
链表是线性存储结构
链表有两个域
数据域:存放各种实际的数据
指针域:存放下一节点的首地址
链表类型
单链表、双链表、循环链表
203 移除链表元素 | 点击查看力扣对应题目
解题思路
有三种方法
删除头结点时另做考虑(由于头结点没有前一个结点)
添加一个虚拟头结点,删除头结点就不用另做考虑
递归
思路分析(递归法)
明确递归的基本条件:如果是空节点,返回null
递归调用下一个节点,并接受返回值
明确每层递归的逻辑:
如果head的节点值是val,那么就删除这个节点并且返回当前节点的下一个节点next
否则把head的next连接到递归返回的头结点上
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} val
* @return {ListNode}
*/
var removeElements = function(head, val) {
if (!head) return null;
next = removeElements(head.next, val);
if(head.val === val){
return next;
}else{
head.next = next;
return head;
}
};
思路分析(虚拟头结点法):
1:定义一个虚拟头结点temp,temp指向链表的头结点(即链表的第一个节点)。定义一个指针curNode指向虚拟头结点
2:遍历链表,当指向虚拟头结点的下一个节点为空时退出循环
3:最终返回虚拟头结点的下一个节点
代码
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} val
* @return {ListNode}
*/
var removeElements = function(head, val) {
const temp = new ListNode(0,head);
let cur = temp;
while(cur.next){
if(cur.next.val === val){
cur.next = cur.next.next;
continue;
}
cur = cur.next;
}
return temp.next;
};
总结
其实自己写代码我写不出来,得看着别人的代码去理解。要弄懂这道题首先得掌握链表知识,尤其是删除节点时,他的链要链接到哪里。
707设计链表
代码
#define MAX(a, b) ((a) > (b) ? (a) : (b))
typedef struct {
struct ListNode *head;
int size;
} MyLinkedList; //链表定义
struct ListNode *ListNodeCreat(int val) {
struct ListNode * node = (struct ListNode *)malloc(sizeof(struct ListNode));
node->val = val;
node->next = NULL;
return node; //初始化
}
MyLinkedList* myLinkedListCreate() {
MyLinkedList * obj = (MyLinkedList *)malloc(sizeof(MyLinkedList));
obj->head = ListNodeCreat(0);
obj->size = 0;
return obj;
}
//获取链表中第一个索引节点的值。如果索引无效,则返回-1
int myLinkedListGet(MyLinkedList* obj, int index) {
if (index < 0 || index >= obj->size) {
return -1;
}
struct ListNode *cur = obj->head;
for (int i = 0; i <= index; i++) {
cur = cur->next;
}
return cur->val;
}
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
if (index > obj->size) {
return;
}
index = MAX(0, index);
obj->size++;
struct ListNode *pred = obj->head;
for (int i = 0; i < index; i++) {
pred = pred->next;
}
struct ListNode *toAdd = ListNodeCreat(val);
toAdd->next = pred->next;
pred->next = toAdd;
}
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
myLinkedListAddAtIndex(obj, 0, val);
}
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
myLinkedListAddAtIndex(obj, obj->size, val);
}
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
if (index < 0 || index >= obj->size) {
return;
}
obj->size--;
struct ListNode *pred = obj->head;
for (int i = 0; i < index; i++) {
pred = pred->next;
}
struct ListNode *p = pred->next;
pred->next = pred->next->next;
free(p);
}
void myLinkedListFree(MyLinkedList* obj) {
struct ListNode *cur = NULL, *tmp = NULL;
for (cur = obj->head; cur;) {
tmp = cur;
cur = cur->next;
free(tmp);
}
free(obj);
}
总结
突然觉得一天写三道算法题对于我来说难度太大了,第一时间不够多,第二第一次刷题很多需要理解的地方,光弄懂一道题就耗时很久。
啊 好难 得坚持---