【数据结构】链表练习题(1)
创始人
2024-05-29 23:42:08
0

练习题

  • 1.移除链表元素(LeetCode203)
  • 2.链表的中间结点(LeetCode876)
  • 3.链表的倒数第k个结点(剑指offer)
  • 4.反转链表(LeetCode206)
  • 5.合并两个有序链表(LeetCode21)
  • 6.链表分割(牛客)
  • 7.链表的回文结构(牛客)


1.移除链表元素(LeetCode203)

给你一个链表的头结点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头结点 。OJ链接

在这里插入图片描述
思路
创建一个新链表,把不等于val的结点尾插到新链表。

代码

struct ListNode 
{int val;struct ListNode* next;	
};
struct ListNode* removeElements(struct ListNode* head, int val)
{struct ListNode* NewHead = NULL;//创建一个新的头结点struct ListNode* cur = head;//用来遍历整个链表struct ListNode* tail = NULL;//指向新链表的最后一个结点,用来尾插数据while (cur){if (cur->val == val)//相等就把这个结点释放{struct ListNode* tmp = cur->next;//储存下一个结点的地址,防止节点释放后找不到下一个结点free(cur);cur = tmp;}else{if (NewHead == NULL)//将头结点指向不等于val的第一个元素{NewHead = tail = cur;}else{tail->next = cur;//尾插新结点tail = tail->next;//指向新链表的最后一个结点}cur = cur->next;}}if (tail)//如果最后一个结点刚好是val,那就tail指向的下一个结点置为NULL{        //如果链表是空,也不会进行对NULL的访问tail->next = NULL;}return NewHead;
}

结果
在这里插入图片描述


2.链表的中间结点(LeetCode876)

给你单链表的头结点 head ,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。OJ链接
在这里插入图片描述
思路
常规思路就是遍历整个链表,得到链表的结点个数从而得到中间结点的下标,再遍历链表找到并返回这个结点。但在介绍一个牛逼的方法:快慢指针,慢指针每次循环走一步,快指针每次循环走两步,最终如果链表长度是奇数,快指针指向链表的最后一个结点,慢指针刚好指向中间结点,如果链表长度是偶数,快指针指向最后一个结点指向的NULL,慢指针指向两个中间结点的第二个结点。
代码

struct ListNode 
{int val;struct ListNode* next;
};
struct ListNode* middleNode(struct ListNode* head) 
{struct ListNode* slow = head, * fast = head;while (fast != NULL && fast->next != NULL)//用&&是因为只要有一个不满足就停止循环{slow = slow->next;fast = fast->next->next;}return slow;
}

结果
在这里插入图片描述


3.链表的倒数第k个结点(剑指offer)

输入一个链表,输出该链表中倒数第k个结点。OJ链接
在这里插入图片描述
思路
还是用快慢指针的方法。要求倒数第k个,快指针就先走k步,此时快指针和慢指针之间的距离为k步,然后和满指针每次走一步,当快指针指向NULL,慢指针和快指针的距离是k步,慢指针和最后一个结点的距离是k-1步,慢指针刚好是倒数第k个结点。
代码

struct ListNode 
{int val;struct ListNode* next;
};
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k) {struct ListNode* slow, * fast = NULL;slow = fast = pListHead;while (k--)//fast先走k步{if (fast == NULL)//走出链表,就直接返回NULL{return NULL;}fast = fast->next;}//此时fast与slow的距离是k,当fast指向NULL,//slow与最后一个节点的距离就是k-1,slow就是倒数第k个while (fast){slow = slow->next;fast = fast->next;}return slow;
}

结果
在这里插入图片描述


4.反转链表(LeetCode206)

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。OJ链接
在这里插入图片描述
思路
法1利用三个指针(n1,n2,n3)实现逆序,n2指向当前结点,n3指向下一个结点,n1指向上一个结点。如图。
在这里插入图片描述

法2创建一个新的链表,取出要逆序链表的节点头插到新链表。
在这里插入图片描述
代码

//法1
struct ListNode 
{int val;struct ListNode* next;};
struct ListNode* reverseList(struct ListNode* head)
{if (head == NULL)//检查是否为空{return NULL;}struct ListNode* n1 = NULL,*n2 =head,*n3 =head->next;while (n2)//一旦n2指向NULL就停止循环{n2->next = n1;n1 = n2;n2 = n3;if (n3)//防止n3越界访问,一旦n3指向NULL,就不再改变{n3 = n3->next;}}return n1;
}
//法2
struct ListNode 
{int val;struct ListNode* next;};
struct ListNode* reverseList(struct ListNode* head)
{struct ListNode* newHead = NULL;struct ListNode* cur = head;//遍历链表while (cur){struct ListNode* next = cur->next;//记住下一个结点cur->next = newHead;//指向头结点指向的结点newHead = cur;cur = next;}return newHead;//不用检查链表为空,因为为空不进入循环,返回NULL
}

结果
在这里插入图片描述


5.合并两个有序链表(LeetCode21)

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。OJ链接在这里插入图片描述
思路
创建一个新链表,以此比较两个升序链表的结点,取小的结点尾插。如图。在这里插入图片描述
代码

struct ListNode 
{int val;struct ListNode* next;};
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{struct ListNode* cur1 = list1, * cur2 = list2;//分别遍历两个链表struct ListNode* head = NULL,*tail = head;//head是新链表的头结点,tail指向新链表的最后一个结点,方便尾插if (list1 == NULL)//如果有链表为空,返回另一个链表{return list2;}if (list2 == NULL){return list1;}while (cur1 && cur2)//有一个是NULL就结束循环{if (cur1->val < cur2->val){if (head == NULL)//考虑到第一次插入节点{head = tail = cur1;}else{tail->next = cur1;tail = tail->next;cur1 = cur1->next;//cur1还指向原来链表的下一个结点,所以不用用指针记录下一个结点}}else{if (head == NULL)//考虑到第一次插入节点{head = tail = cur2;}else{tail->next = cur2;tail = tail->next;cur2 = cur2->next;//cur1还指向原来链表的下一个结点,所以不用用指针记录下一个结点}}}if (cur1 == NULL)//说明list2还有结点,直接插到新链表的尾部即可{tail->next = cur2;}if (cur2 == NULL){tail->next = cur1;}return head;
}

结果
在这里插入图片描述


6.链表分割(牛客)

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。OJ链接
思路
把小于x的结点插到一个链表,大于或等于x的结点插到另一个链表,然后把两个链表链接起来。
预备知识
在使用单链表时,我们通常用用一个指针指向第一个结点,作为头结点,而这道题得使用哨兵位的头结点,用一个结点来指向链表的第一个结点。什么是哨兵位的头结点?顾名思义就是一个结点,这个结点不存储数据,只指向第一个结点,至于它的作用后面会讲到,现在只需知道它是一个不存储数据的、指向第一个结点的结点
在这里插入图片描述

代码

struct ListNode {int val;struct ListNode* next;
};
struct ListNode* partition(struct ListNode* pHead, int x)
{struct ListNode* smallGuard = (struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* bigGuard = (struct ListNode*)malloc(sizeof(struct ListNode));smallGuard->next = NULL;bigGuard->next = NULL;struct ListNode* smallTail = smallGuard, * bigTail = bigGuard, * cur = pHead;while (cur){if (cur->val < x){smallTail->next = cur;smallTail = smallTail->next;}else{bigTail->next = cur;bigTail = bigTail->next;}cur = cur->next;}smallTail->next = bigGuard->next;//将大链表链接到另一个链表,bigTail->next = NULL;//同时记得将大链表的最后一个节点指向NULL,防止其指向链表的另一个节点,导致环形链表pHead = bigGuard->next;//将新链表的头节点赋值给phead,因为哨兵位的头节点要释放free(bigGuard);free(smallGuard);bigGuard = NULL;smallGuard = NULL;return pHead;
}

结果
在这里插入图片描述

哨兵位头节点的作用
在这里插入图片描述


7.链表的回文结构(牛客)

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
在这里插入图片描述
思路
先找到中间节点(可以用前面的函数),从中间节点开始,对后半段进行逆序(用前面的函数),最后判断前半段和后半段是否相等。
在这里插入图片描述

代码

struct ListNode {int val;struct ListNode* next;
};
struct ListNode* middleNode(struct ListNode* head) {struct ListNode* slow, * fast;slow = fast = head;while ((fast != NULL) && (fast->next != NULL)) {slow = slow->next;fast = fast->next->next;}return slow;
}
struct ListNode* reverseList(struct ListNode* head) {struct ListNode* newHead = NULL;struct ListNode* cur = head;while (cur) {struct ListNode* next = cur->next;cur->next = newHead;newHead = cur;cur = next;}return newHead;
}
bool chkPalindrome(struct ListNode* head)
{struct ListNode* mid = middleNode(head);struct ListNode* rhead = reverseList(head);while (rhead && head)//当有偶数个节点时,rhead先遇到NULL,当有奇数个节点时,head和rhead同时遇到NULL{if (rhead->val != head->val){return false;}}return true;
}

结果
在这里插入图片描述


相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...