目录
思路一:先求链表总长度,然后长度除以2得到中间位置,再遍历找到中间节点。
思路三:找链表中间节点,以其为新链表的头节点,反转新链表,遍历与原链表比较
1.移除链表元素
题目链接:
203. 移除链表元素 - 力扣(LeetCode)
https://leetcode.cn/problems/remove-linked-list-elements/description/题目描述:
给你一个链表的头节点
head和一个整数val,请你删除链表中所有满足Node.val == val的节点,并返回 新的头节点 。
思路:创建新链表
struct ListNode* removeElements(struct ListNode* head, int val) {
struct ListNode* newhead = (struct ListNode*)malloc(sizeof(struct ListNode));
newhead->next=NULL;
struct ListNode* newtail=newhead;
struct ListNode* pcur=head;
while(pcur!=NULL)
{
if((pcur->val)!=val)
{
newtail->next=pcur;
newtail=newtail->next;
}
pcur=pcur->next;
}
newtail->next=NULL;
return newhead->next;
}
2.反转链表
题目链接:
206. 反转链表 - 力扣(LeetCode)
https://leetcode.cn/problems/reverse-linked-list/description/题目简述:
给你单链表的头节点
head,请你反转链表,并返回反转后的链表。
思路一:创建新链表头插
struct ListNode* reverseList(struct ListNode* head) {
struct ListNode* newhead=NULL;
struct ListNode* next=NULL;
while(head)
{
next=head->next; //一定要保存下一个节点的位置
head->next=newhead; //不然这步将下一个节点销毁了
newhead=head;
head=next;
}
return newhead;
}
思路二:创建三个指针,改变链表中指针的方向
struct ListNode* reverseList(struct ListNode* head) {
if(head==NULL)
{
return head;
}
struct ListNode* n1=NULL,*n2=head,*n3=n2->next;
while(n2)
{
n2->next=n1;
n1=n2;
n2=n3;
if(n3)
n3=n3->next;
}
return n1;
}
3.链表的中间结点
题目链接:
876. 链表的中间结点 - 力扣(LeetCode)
https://leetcode.cn/problems/middle-of-the-linked-list/description/题目简述:
给你单链表的头结点
head,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
思路一:先求链表总长度,然后长度除以2得到中间位置,再遍历找到中间节点。
struct ListNode* middleNode(struct ListNode* head) {
int len=0;
struct ListNode* p=head;
while(head)
{
head=head->next;
len++;
}
int mid=len/2;
while(mid)
{
p=p->next;
mid--;
}
return p;
}
思路二:快慢指针
struct ListNode* middleNode(struct ListNode* head) {
struct ListNode* fast=head;
struct ListNode* slow=head;
while(fast && fast->next)//绝对不可以写成fast->next && fast
{
fast=fast->next->next;
slow=slow->next;
}
return slow;
}
4.合并两个有序链表
题目链接:
21. 合并两个有序链表 - 力扣(LeetCode)
https://leetcode.cn/problems/merge-two-sorted-lists/description/题目描述:
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
思路:创建新链表,比较两个原链表,谁小谁尾插
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
struct ListNode* newnode=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* newhead=newnode;
newnode->next=NULL;
while(list1 && list2)
{
if(list1->val < list2->val)
{
newnode->next=list1;
list1=list1->next;
}
else {
newnode->next=list2;
list2=list2->next;
}
newnode=newnode->next;
}
if(list1!=NULL)
{
newnode->next=list1;
}
if(list2!=NULL)
{
newnode->next=list2;
}
return newhead->next;
}
5.链表分割
题目链接:
链表分割_牛客题霸_牛客网
https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70题目描述:
现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针
思路:新建两个连表,分别放<x和>=x的值,再将两个链表相连
ListNode* partition(ListNode* pHead, int x) {
ListNode* lessHead,*lessTail;
lessHead=lessTail=(ListNode*)malloc(sizeof(ListNode));
ListNode* greaterHead,*greaterTail;
greaterHead=greaterTail=(ListNode*)malloc(sizeof(ListNode));
while(pHead)
{
if(pHead->val<x)
{
lessTail->next=pHead;
lessTail=lessTail->next;
}
else {
greaterTail->next=pHead;
greaterTail=greaterTail->next;
}
pHead=pHead->next;
}
greaterTail->next=NULL;
lessTail->next=greaterHead->next;
return lessHead->next;
}
6.链表的回文结构
题目链接:
链表的回文结构_牛客题霸_牛客网
https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa题目描述:
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
思路一:创建新链表,将原链表头插,对比两个链表是否相同
#include <cstdio>
#include <cstdlib>
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
ListNode* cur = A;
ListNode* newA = NULL;
while (cur) {
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
node->val=cur->val;
node->next=NULL;
if(newA==NULL) {
newA=node;
}
else {
node->next=newA;
newA=node;
}
cur=cur->next;
}
while(A)
{
if(A->val!=newA->val)
{
return false;
}
A=A->next;
newA=newA->next;
}
return true;
}
};
思路二:创建数组法
#include <cstdio>
#include <cstdlib>
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
int arr[900] = {0};
int i = 0;
while (A) {
arr[i++] = A->val;
A = A->next;
}
int left = 0;
int right = i - 1;
while (left < right) {
if (arr[left] != arr[right]) {
return false;
}
left++;
right--;
}
return true;
}
};
思路三:找链表中间节点,以其为新链表的头节点,反转新链表,遍历与原链表比较
#include <cstdio>
#include <cstdlib>
class PalindromeList {
public:
ListNode* middleNode(ListNode* head) {
ListNode* fast = head;
ListNode* slow = head;
while (fast && fast->next) { //绝对不可以写成fast->next && fast
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
ListNode* reverseList(ListNode* head) {
if (head == NULL) {
return head;
}
ListNode* n1 = NULL, *n2 = head, *n3 = n2->next;
while (n2) {
n2->next = n1;
n1 = n2;
n2 = n3;
if (n3)
n3 = n3->next;
}
return n1;
}
bool chkPalindrome(ListNode* A) {
//找中间节点
ListNode* mid=middleNode(A);
//反转新链表
ListNode* right=reverseList(mid);
//遍历比较
ListNode* left=A;
while(right)
{
if(right->val!=left->val)
{
return false;
}
right=right->next;
left=left->next;
}
return true;
}
};
7.相交链表
题目链接:
160. 相交链表 - 力扣(LeetCode)
https://leetcode.cn/problems/intersection-of-two-linked-lists/description/题目描述:
给你两个单链表的头节点
headA和headB,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回null。
思路:求两个链表的长度,让长链表先走长度差,让后长短链表同步遍历找相同节点
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
int la=0,lb=0;
struct ListNode *pa=headA;
struct ListNode *pb=headB;
while(pa)
{
la++;
pa=pa->next;
}
while(pb)
{
lb++;
pb=pb->next;
}
int gap=abs(la-lb);
struct ListNode *longlist=headA;
struct ListNode *shortlist=headB;
if(la<lb)
{
longlist=headB;
shortlist=headA;
}
while(gap--)
{
longlist=longlist->next;
}
while(shortlist)
{
if(shortlist==longlist)
{
return shortlist;
}
shortlist=shortlist->next;
longlist=longlist->next;
}
return NULL;
}
8.环形链表1
题目链接:
141. 环形链表 - 力扣(LeetCode)
https://leetcode.cn/problems/linked-list-cycle/description/题目描述:
给你一个链表的头节点
head,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪
next指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数pos来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos不作为参数进行传递 。仅仅是为了标识链表的实际情况。如果链表中存在环 ,则返回
true。 否则,返回false。
思路:利用快慢指针,若快慢指针相遇,则链表有环
bool hasCycle(struct ListNode *head) {
struct ListNode *fast=head;
struct ListNode *slow=head;
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
{
return true;
}
}
return false;
}
9.环形链表2
题目链接:
142. 环形链表 II - 力扣(LeetCode)
https://leetcode.cn/problems/linked-list-cycle-ii/description/题目描述:
给定一个链表的头节点
head,返回链表开始入环的第一个节点。 如果链表无环,则返回null。如果链表中有某个节点,可以通过连续跟踪
next指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数pos来表示链表尾连接到链表中的位置(索引从 0 开始)。如果pos是-1,则在该链表中没有环。注意:pos不作为参数进行传递,仅仅是为了标识链表的实际情况。不允许修改 链表。
思路:用快慢指针找到相遇节点,利用“相遇节点到头节点的距离==头节点到入环节点的距离”求出入环节点
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode *fast=head;
struct ListNode *slow=head;
struct ListNode *pcur=head;
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
{
while(slow!=pcur)
{
slow=slow->next;
pcur=pcur->next;
}
return slow;
}
}
return NULL;
}





