203.移除链表元素
题目链接:力扣-203.移除链表元素
思路:
这里就涉及两种链表操作的方式:
- 直接使用原来的链表来进行删除操作。
- 设置一个虚拟头结点在进行删除操作。
第二种方式做这到题更简单一点,第一种需要注意 head.val == val 的特殊情况,不能与其他情况放在一个循环里判断,会导致访问了已经释放的内存的编译错误。而使用虚拟头结点不需要单独判断这种情况。
第一种代码:
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode *s;
while(head && head->val == val){
s = head;
head = head->next;
free(s);
}
struct ListNode *p = head;
while(p && p->next){
if(p->next->val == val){
s = p->next;
p->next = s->next;
free(s);
}
else{
p = p->next;
}
}
return head;
}
第二种代码(虚拟头):
struct ListNode* removeElements(struct ListNode* head, int val){
typedef struct ListNode ListNode;
ListNode *shead = (ListNode*)malloc(sizeof(ListNode));
shead->next =head;
ListNode *p = shead;
ListNode *q;
while(p && (q = p->next)){
if(q->val == val){
p->next = q->next;
free(q);
}
else{
p = p->next;
}
}
return shead->next;
}
206.反转链表
题目链接:力扣-206.反转链表
思路:
- 双指针法
- 递归法(从前往后翻转指针指向、从后往前翻转指针指向)
定义两个指针,一个指向头节点,一个指向NULL,通过一个while循环进行整个链表的反转。递归法相对抽象一些,但和双指针法是一样的逻辑。
双指针法:
struct ListNode* reverseList(struct ListNode* head){
struct ListNode*p = head;
struct ListNode*q = NULL;
struct ListNode*s;
while(p){
s = p;
p = p->next;
s->next = q;
q = s;
}
return s;
}
递归法:
struct ListNode* reverse(struct ListNode* p, struct ListNode* q){
if(!q){
return p;
}
struct ListNode*s = q->next;
q->next = p;
return reverse(q, s);
}
struct ListNode* reverseList(struct ListNode* head){
return reverse(NULL, head);
}
707.设计链表
题目链接:力扣-707.设计链表
思路:
这是一道考察链表综合操作的题目,比较容易出错,使用虚拟头结点会更方便。
这道题目设计链表的五个接口:
- 获取链表第index个节点的数值
- 在链表的最前面插入一个节点
- 在链表的最后面插入一个节点
- 在链表第index个节点前面插入一个节点
- 删除链表的第index个节点
链表的知识点有些遗忘了,需要尽快复习,二刷时注意。
typedef struct MyLinkedList{
int val;
struct MyLinkedList *next;
} MyLinkedList;
MyLinkedList* myLinkedListCreate() {
MyLinkedList* head = (MyLinkedList *)malloc(sizeof (MyLinkedList));
head->next = NULL;
return head;
}
int myLinkedListGet(MyLinkedList* obj, int index) {
MyLinkedList *cur = obj->next;
for (int i = 0; cur != NULL; i++){
if (i == index){
return cur->val;
}
else{
cur = cur->next;
}
}
return -1;
}
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
MyLinkedList *nhead = (MyLinkedList *)malloc(sizeof (MyLinkedList));
nhead->val = val;
nhead->next = obj->next;
obj->next = nhead;
}
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
MyLinkedList *cur = obj;
while(cur->next != NULL){
cur = cur->next;
}
MyLinkedList *ntail = (MyLinkedList *)malloc(sizeof (MyLinkedList));
ntail->val = val;
ntail->next = NULL;
cur->next = ntail;
}
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
if (index == 0){
myLinkedListAddAtHead(obj, val);
return;
}
MyLinkedList *cur = obj->next;
for (int i = 1 ;cur != NULL; i++){
if (i == index){
MyLinkedList* newnode = (MyLinkedList *)malloc(sizeof (MyLinkedList));
newnode->val = val;
newnode->next = cur->next;
cur->next = newnode;
return;
}
else{
cur = cur->next;
}
}
}
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
if (index == 0){
MyLinkedList *tmp = obj->next;
if (tmp != NULL){
obj->next = tmp->next;
free(tmp);
}
return;
}
MyLinkedList *cur = obj->next;
for (int i = 1 ;cur != NULL && cur->next != NULL; i++){
if (i == index){
MyLinkedList *tmp = cur->next;
if (tmp != NULL) {
cur->next = tmp->next;
free(tmp);
}
return;
}
else{
cur = cur->next;
}
}
}
void myLinkedListFree(MyLinkedList* obj) {
while(obj != NULL){
MyLinkedList *tmp = obj;
obj = obj->next;
free(tmp);
}
}
总结:
今天的题目都不算难,链表不太熟练,很多的知识点都生疏了。