• 【数据结构与算法】---OJ手撕链表题


    作者:旧梦拾遗186

    专栏:数据结构成长日记

    每日励志:

    你没资格半途而废,你没资格破罐子破摔,你只能让自己活得比任何人都好,比任何人都强大,你已经没有退路。

    前言:

    小编带大家学习链表OJ题。

    目录

    移除链表元素

    题解

    反转链表

    题解

    合并两个有序链表

    题解:


    移除链表元素

    移除链表元素https://leetcode.cn/problems/remove-linked-list-elements/

    给你一个链表的头节点 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

    题解

    思路一:一种比较普遍的方式,边遍历边找不同。我们可以通过定义两个指针,一个指向头节点,一个置为NULL。当遇到值为相同的时候,直接跳过去。指向下一位。同时,我们要去注意头删的问题,因为题目中给出的函数具有头结点head。

    1. struct ListNode* removeElements(struct ListNode* head, int val){
    2. struct ListNode* cur=head;
    3. struct ListNode* pre=NULL;
    4. while(cur)
    5. {
    6. if(cur->val==val)
    7. {
    8. if(cur==head)
    9. {
    10. head=head->next;
    11. free(cur);
    12. cur=head;
    13. }
    14. else
    15. {
    16. pre->next=cur->next;
    17. free(cur);
    18. cur=pre->next;
    19. }
    20. }
    21. else
    22. {
    23. pre=cur;
    24. cur=cur->next;
    25. }
    26. }
    27. return head;
    28. }

     思路二:给一个新的链表,不是val的结点尾插到新链表即可。最后结点置为NULL。同时,还是要注意头结点的问题

    1. struct ListNode* removeElements(struct ListNode* head, int val){
    2. struct ListNode* cur=head;
    3. struct ListNode* tail=NULL;
    4. struct ListNode* newnode=NULL;
    5. while(cur)
    6. {
    7. if(cur->val!=val)
    8. {
    9. if(tail==NULL)
    10. {
    11. newnode=tail=cur;
    12. }
    13. else
    14. {
    15. tail->next=cur;
    16. tail=tail->next;
    17. }
    18. cur=cur->next;
    19. }
    20. else
    21. {
    22. struct ListNode* del=cur;
    23. cur=cur->next;
    24. free(del);
    25. }
    26. }
    27. if(tail)
    28. {
    29. tail->next=NULL;
    30. }
    31. return newnode;
    32. }

    我们不难发现,如果没有头结点,我们都要去关注,所以我们可以给出带头结点(哨兵链表)的单链表来进行实现

    1. struct ListNode* removeElements(struct ListNode* head, int val){
    2. struct ListNode*cur = head;
    3. struct ListNode*guard = (struct ListNode*)malloc(sizeof(struct ListNode));
    4. struct ListNode*tail = guard;
    5. while(cur)
    6. {
    7. if(cur->val != val)
    8. {
    9. // tail=cur;
    10. tail->next = cur;
    11. tail = tail->next;
    12. cur = cur->next;
    13. }
    14. else
    15. {
    16. struct ListNode*del = cur;
    17. cur = cur->next;
    18. free(del);
    19. }
    20. }
    21. if(tail)
    22. tail->next = NULL;
    23. head = guard->next;
    24. free(guard);
    25. return head;
    26. }

    有头结点之后我们就不需要去考虑删除第一个元素的事了。

    反转链表

    反转链表https://leetcode.cn/problems/reverse-linked-list/

    给你单链表的头节点 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. struct ListNode* cur=head;
    3. struct ListNode* newhead=NULL;
    4. while(cur)
    5. {
    6. struct ListNode* next=cur->next;
    7. cur->next=newhead;
    8. newhead=cur;
    9. cur=next;
    10. }
    11. return newhead;
    12. }

     

    思路二:直接把指针的方向进行翻转即可,使得链表翻转

    1. struct ListNode* reverseList(struct ListNode* head){
    2. struct ListNode* cur=head;
    3. struct ListNode* pre=NULL;
    4. while(cur)
    5. {
    6. struct ListNode* next=cur->next;
    7. cur->next=pre;
    8. pre=cur;
    9. cur=next;
    10. }
    11. return pre;
    12. }

    合并两个有序链表

     力扣https://leetcode.cn/problems/merge-two-sorted-lists/description/

    将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

    示例 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 均按 非递减顺序 排列

    来源:力扣(LeetCode)
    链接:https://leetcode.cn/problems/merge-two-sorted-lists
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    题解:

    思路:比较简单,创建一个带头结点的链表,去比较数据的大小尾插到新链表的后面即可。

    1. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    2. struct ListNode* cur1=list1;
    3. struct ListNode* cur2=list2;
    4. struct ListNode* guard=(struct ListNode*)malloc(sizeof(struct ListNode));
    5. guard->next=NULL;
    6. struct ListNode* tail=guard;
    7. while(cur1&&cur2)
    8. {
    9. if(cur1->val->val)
    10. {
    11. tail->next = cur1;
    12. cur1 = cur1->next;
    13. }
    14. else
    15. {
    16. tail->next = cur2;
    17. cur2 = cur2->next;
    18. }
    19. tail = tail->next;
    20. }
    21. if(cur1)
    22. {
    23. tail->next=cur1;
    24. }
    25. if(cur2)
    26. {
    27. tail->next=cur2;
    28. }
    29. struct ListNode* head=guard->next;
    30. free(guard);
    31. return head;
    32. }

  • 相关阅读:
    web前端面试题附答案044 - vue获取param参数,有什么缺点吗?
    新版绿豆视频APP视频免授权源码 V6.6插件版
    某省医保局:强化医保信息化高质量建设,提升数字医疗保障服务能力
    如何突破测试/开发程序员思维?一种不一样的感觉......
    时间格式记录
    javascript的数组对象常用方法
    Android入门第11天-Android中RadioButton的使用
    花书——PyTorch版本
    SpringBoot整合任务系统(quartz和SpringTask)
    STM32(TIM定时器中断)
  • 原文地址:https://blog.csdn.net/weixin_67900732/article/details/126200483