🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
目录
移除链表元素
给你一个链表的头节点
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的前后两个节点,所以采用双指针的方法
1. struct ListNode* removeElements(struct ListNode* head, int val) 2. { 3. //这就是第一种情况,如果头为空,直接返回空值 4. if(head==NULL) 5. { 6. return NULL; 7. } 8. struct ListNode* prev=NULL,*cur=head;//双指针的方法,一前一后的指针 9. while(cur)//通过循环遍历整个链表 10. { 11. if(cur->val==val) 12. { 13. if(prev==NULL) 14. { 15. cur=cur->next; 16. head=cur; 17. } 18. else 19. { 20. prev->next=cur->next; 21. cur=cur->next; 22. } 23. } 24. else 25. { 26. prev=cur; 27. cur=cur->next; 28. } 29. } 30. return head; 31. }
反转链表
给你单链表的头节点
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
解题思路:
解题的关键在于我们需要大致判断链表的几种情况,然后通过调试,一步一步通过测试用例,这题分为两种情况,第一种链表为空的时候,就直接返回空指针,第二种链表不为空时,我们采用的是在原有的链表上进行改动,就是将原有的节点指向改变,这里需要记录三个节点的位置,所以需要三个指针
1. struct ListNode* reverseList(struct ListNode* head) 2. { 3. if(head==NULL) 4. { 5. return NULL; 6. } 7. struct ListNode* n1=NULL; 8. struct ListNode* n2=head; 9. struct ListNode* n3=head->next; 10. while(n2) 11. { 12. n2->next=n1; 13. n1=n2; 14. n2=n3; 15. if(n3!=NULL) 16. { 17. n3=n3->next; 18. } 19. } 20. return n1; 21. }
合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 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值大小情况,谁小就让头指针去指向谁,然后,我们需要遍历两个链表,只要其中一个链表为空,就跳出循环
1. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 2. { 3. if(list1==NULL) 4. { 5. return list2; 6. } 7. if(list2==NULL) 8. { 9. return list1; 10. } 11. if(list1==NULL&&list2==NULL) 12. { 13. return NULL; 14. } 15. struct ListNode* cur=NULL; 16. struct ListNode* head=NULL; 17. while(list1&&list2) 18. { 19. if(list1->val<list2->val) 20. { 21. if(head==NULL) 22. { 23. head=cur=list1; 24. } 25. else 26. { 27. cur->next=list1; 28. cur=list1; 29. } 30. list1=list1->next; 31. } 32. else 33. { 34. if(head==NULL) 35. { 36. head=cur=list2; 37. } 38. else 39. { 40. cur->next=list2; 41. cur=list2; 42. } 43. list2=list2->next; 44. } 45. } 46. if(list1==NULL) 47. { 48. cur->next=list2; 49. } 50. if(list2==NULL) 51. { 52. cur->next=list1; 53. } 54. return head; 55. }
总结
做链表的题的确需要一番思索,我在做第一个题的时候,做了大概两天时间,但还是没有完全通过测试用例(可能我比较愚笨),我就放弃了这道题。过了几天我重新去做这道题,通过了一些方法,最终解决了这道题。这些方法我归结了一下,可以适用于大部分链表类的测试题,第一:画图!画图!画图!重要的事情说三遍,我感觉之所以之前没有做出来这道题,是我没有认真画图的原因,认真画图非常关键,为什么强调认真画图,我之前做题的时候,就老是把图画的很乱,而且画图的位置空间也不足,导致有时候一次测试用例都没有走完,我就放弃了,后来做题过程中,我就认认真真画图,然后走完了几个测试用例,我就这样完成了这道题。第二:有时候我们感觉逻辑没有问题,但是还是存在错误,我们就需要进行调试了,因为这些题目是在线OJ题,一般是不能调试的,所以我们需要在自己的编译器上进行调试,进行调试后,我们就能很容易的到出错的位置,这样有助于我们完成这道题。
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸