🐶博主主页:@ᰔᩚ. 一怀明月ꦿ
❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++
🔥座右铭:“不要等到什么都没有了,才下定决心去做”
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
目录
移除链表元素
反转链表
合并两个有序链表
总结
移除链表元素
给你一个链表的头节点
head
和一个整数val
,请你删除链表中所有满足Node.val == val
的节点,并返回 新的头节点 。示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]示例 2:
输入:head = [], val = 1 输出:[]示例 3:
输入:head = [7,7,7,7], val = 7 输出:[]提示:
- 列表中的节点数目在范围
[0, 104]
内1 <= Node.val <= 50
0 <= val <= 50
解题思路:
解题的关键在于我们需要大致判断链表的几种情况,然后通过调试,一步一步通过测试用例,这里我们可以分为三种链表,第一种就是链表为空,这种直接返回空指针,第二种就是链表的第一个节点的val值等于测试用例的val,这里我们就需要进行换头处理,就是跳过第一个节点,把第二个节点当作头,第三种val值在链表非头的位置,从头开始寻找,找到等于val的节点,将val的上个节点连接到val的下个节点。因为我们需要知道val的前后两个节点,所以采用双指针的方法
struct ListNode* removeElements(struct ListNode* head, int val) {//这就是第一种情况,如果头为空,直接返回空值if(head==NULL){return NULL;}struct ListNode* prev=NULL,*cur=head;//双指针的方法,一前一后的指针while(cur)//通过循环遍历整个链表{if(cur->val==val){if(prev==NULL){cur=cur->next;head=cur;}else{prev->next=cur->next;cur=cur->next;}}else{prev=cur;cur=cur->next;}}return head; }
反转链表
给你单链表的头节点
head
,请你反转链表,并返回反转后的链表。示例 1:
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]示例 2:
输入:head = [1,2] 输出:[2,1]示例 3:
输入:head = [] 输出:[]提示:
- 链表中节点的数目范围是
[0, 5000]
-5000 <= Node.val <= 5000
解题思路:
解题的关键在于我们需要大致判断链表的几种情况,然后通过调试,一步一步通过测试用例,这题分为两种情况,第一种链表为空的时候,就直接返回空指针,第二种链表不为空时,我们采用的是在原有的链表上进行改动,就是将原有的节点指向改变,这里需要记录三个节点的位置,所以需要三个指针
struct ListNode* reverseList(struct ListNode* head) {if(head==NULL){return NULL;}struct ListNode* n1=NULL;struct ListNode* n2=head;struct ListNode* n3=head->next;while(n2){n2->next=n1;n1=n2;n2=n3;if(n3!=NULL){n3=n3->next;}}return n1; }
合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:
输入:l1 = [1,2,4], l2 = [1,3,4] 输出:[1,1,2,3,4,4]示例 2:
输入:l1 = [], l2 = [] 输出:[]示例 3:
输入:l1 = [], l2 = [0] 输出:[0]提示:
- 两个链表的节点数目范围是
[0, 50]
-100 <= Node.val <= 100
l1
和l2
均按 非递减顺序 排列解题思路:
解题的关键在于我们需要大致判断链表的几种情况,然后通过调试,一步一步通过测试用例,这个链表分为四种情况,第一种list1为空时,直接返回list2,第二种list2为空时,直接返回list1,第三种list1和list2都为空时,直接返回空指针,第四种list1和list2都不为空时,首先我们的需要一个头指针去保存头节点的位置,我们需要去判断list1和list2的头节点的val值大小情况,谁小就让头指针去指向谁,然后,我们需要遍历两个链表,只要其中一个链表为空,就跳出循环
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {if(list1==NULL){return list2;}if(list2==NULL){return list1;}if(list1==NULL&&list2==NULL){return NULL;}struct ListNode* cur=NULL;struct ListNode* head=NULL;while(list1&&list2){if(list1->val<list2->val){if(head==NULL){head=cur=list1;}else{cur->next=list1;cur=list1;}list1=list1->next;}else{if(head==NULL){head=cur=list2;}else{cur->next=list2;cur=list2;}list2=list2->next;}}if(list1==NULL){cur->next=list2;}if(list2==NULL){cur->next=list1;}return head; }
总结
做链表的题的确需要一番思索,我在做第一个题的时候,做了大概两天时间,但还是没有完全通过测试用例(可能我比较愚笨),我就放弃了这道题。过了几天我重新去做这道题,通过了一些方法,最终解决了这道题。这些方法我归结了一下,可以适用于大部分链表类的测试题,第一:画图!画图!画图!重要的事情说三遍,我感觉之所以之前没有做出来这道题,是我没有认真画图的原因,认真画图非常关键,为什么强调认真画图,我之前做题的时候,就老是把图画的很乱,而且画图的位置空间也不足,导致有时候一次测试用例都没有走完,我就放弃了,后来做题过程中,我就认认真真画图,然后走完了几个测试用例,我就这样完成了这道题。第二:有时候我们感觉逻辑没有问题,但是还是存在错误,我们就需要进行调试了,因为这些题目是在线OJ题,一般是不能调试的,所以我们需要在自己的编译器上进行调试,进行调试后,我们就能很容易的到出错的位置,这样有助于我们完成这道题。
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸