目录
一、移除链表元素
203. 移除链表元素 - 力扣(LeetCode) (leetcode-cn.com)
题目:给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
图解分析:
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode* cur = head;
struct ListNode* prev = NULL;
//从前往后一直寻找,直到为空
while(cur)
{
if(cur->val == val)
{
//如果第一个就是val
if(cur == head)
{
head = cur->next;
free(cur);
cur = head;
}
else
{
prev->next = cur->next;
free(cur);
cur = prev;
}
}
else
{
prev = cur;
cur = cur ->next;
}
}
return head;
}
运行结果:
二、反转链表
206. 反转链表 - 力扣(LeetCode) (leetcode-cn.com)
题目:给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
图解分析:
思路一:
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* prev = NULL;
struct ListNode* tail = NULL;
struct ListNode* cur = head;
while(cur)
{
tail = cur->next;
cur->next = prev;
prev = cur;
cur = tail;
}
return prev;
}
运行结果:
思路二:头插
图解分析:
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head)
{
//如果链表为空的情况
if(head == NULL)
{
return NULL;
}
struct ListNode* cur = head;
struct ListNode* next = head->next;
struct ListNode* newnode = NULL;
while(cur)
{
//头插
cur->next = newnode;
newnode = cur;
//迭代
cur = next;
if(next != NULL)
{
next = cur->next;
}
}
return newnode;
}
//注意点:
struct ListNode* reverseList(struct ListNode* head)
{
//如果链表为空的情况
// if(head == NULL)
// {
// return NULL;
// }
struct ListNode* cur = head;
struct ListNode* newnode = NULL;
while(cur)
{
struct ListNode* next = cur->next;
//如果在里面创建next,cur->next,head为空的情况就不要判断,因为不会执行到里面的代码
//头插
cur->next = newnode;
newnode = cur;
//迭代
cur = next;
if(next != NULL)
{
next = cur->next;
}
}
return newnode;
}
运行结果:
三、链表的中间结点
876. 链表的中间结点 - 力扣(LeetCode) (leetcode-cn.com)
题目:给定一个头结点为 head
的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
思路一:先计算节点个数,然后走节点个数的一半,找到他们的中间节点
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* cur = head;
int count = 0;
//先从头往后,记录节点个数
while (cur != NULL)
{
count++;
cur = cur->next;
}
cur = head;
int num = count / 2;
int i = 0;
for (i = 0; i < num; i++)
{
cur = cur->next;
}
return cur;
}
运行结果:
思路二:快慢指针
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* fast = head;
struct ListNode* slow = head;
//奇数 尾(fast->next)结束,偶数 fast == NULL结束
//俩个都不为空继续,有一个为空结束
while(fast && fast->next)
{
fast = fast ->next->next;
slow = slow ->next;
}
return slow;
}
运行结果:
四、链表中倒数第k个结点
链表中倒数第k个结点_牛客题霸_牛客网 (nowcoder.com)
fast先走k步,如果k大于链表长度,则直接返回NULL,然后fast和low同时走,最后low所指向的位置记为倒数第k个节点
代码:
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
//快慢指针
//fast先走k步
//slow和fast再一起走,fast == NULL时,slow就是倒数第k个
struct ListNode* fast = pListHead;
struct ListNode* slow = pListHead;
while(k--)
{
//k 大于链表的长度
if(fast == NULL)//
{
return NULL;
}
fast = fast->next;
}
while(fast != NULL)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
运行结果:
五、合并俩个有序链表
21. 合并两个有序链表 - 力扣(LeetCode) (leetcode-cn.com)
思路一:
解析:
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
//如果list1为空,但list不为空,则返回list2
if(list1 == NULL)
{
return list2;
}
if(list2 == NULL)
{
return list1;
}
struct ListNode* head = NULL;
struct ListNode* tail = NULL;
//结束条件:俩个链表有一个为空,就将另一个链接到后面,俩个链表的最后指向的都是NULL
while(list1 && list2)
{
if(list1->val <= list2->val)
{
if(head == NULL)
{
head = tail = list1;
}
else
{
tail->next = list1;
tail = tail->next;
}
list1 = list1->next;
}
else
{
if(head == NULL)
{
head = tail = list2;
}
else
{
tail->next = list2;
tail = tail->next;
}
list2 = list2->next;
}
}
if(list1)
{
tail ->next = list1;
}
if(list2)
{
tail ->next = list2;
}
return head;
}
运行结果:
思路二 优化:将第一次为空的情况先判断
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
//如果list1为空,但list不为空,则返回list2
if(list1 == NULL)
{
return list2;
}
if(list2 == NULL)
{
return list1;
}
struct ListNode* head = NULL;
struct ListNode* tail = NULL;
//先进行判断第一次head = NULL的情况
if(list1->val <= list2->val)
{
head = tail = list1;
list1 = list1->next;
}
else
{
head = tail = list2;
list2 = list2->next;
}
//结束条件:俩个链表有一个为空,就将另一个链接到后面,俩个链表的最后指向的都是NULL
while(list1 && list2)
{
if(list1->val <= list2->val)
{
tail->next = list1;
tail = tail->next;
list1 = list1->next;
}
else
{
tail->next = list2;
tail = tail->next;
list2 = list2->next;
}
}
if(list1)
{
tail ->next = list1;
}
if(list2)
{
tail ->next = list2;
}
return head;
}
运行结果:
思路三 优化.多一个哨兵位的头结点,这个节点不存储有效数据
有哨兵位的话,就是head每次指向的都是这个哨兵位,不需要去改变它的指向了,不需要去判断head 为NULL的情况
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
//如果设立一个头结点,那么就不需要判断第一次head = NULL的情况
struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
//memset(newnode,0,sizeof(newnode));
//如果list1为空,但list不为空,则返回list2
if(list1 == NULL)
{
return list2;
}
if(list2 == NULL)
{
return list1;
}
struct ListNode* head = newnode;
struct ListNode* tail = newnode;
//结束条件:俩个链表有一个为空,就将另一个链接到后面,俩个链表的最后指向的都是NULL
while(list1 && list2)
{
if(list1->val <= list2->val)
{
tail->next = list1;
tail = tail->next;
list1 = list1->next;
}
else
{
tail->next = list2;
tail = tail->next;
list2 = list2->next;
}
}
if(list1)
{
tail ->next = list1;
}
if(list2)
{
tail ->next = list2;
}
//malloc不释放会导致内存泄漏,所以要先保存头结点的下一个节点
//然后将malloc出来的头结点释放掉
struct ListNode* NewnodeNext = head->next;
free(head);//head是struct ListNode大小,所以向后访问这么多字节,然后将这部分空间释放掉
return NewnodeNext;
}
运行结果:
本篇为链表相关oj题,如有问题请在评论区,多多评论,共同学习,感谢^_^