• 链表oj题(第一弹)


    通过前两篇博客我们了解了链表的实现,那么今天我们来看看链表的oj题是如何完成的。

    1、移除链表元素

     题目要求我们删掉与val相同的节点。

    方法一:我们可以写一个循环,首先创建两个节点,一个头节点,一个尾节点,开始时为空指针,将不为val的值尾插到新的尾后,当值与val相等,我们先创建next将cur释放掉后直接将next赋给cur即可。

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. struct ListNode* removeElements(struct ListNode* head, int val)
    9. {
    10. if(head == NULL)
    11. {
    12. return NULL;
    13. }
    14. struct ListNode* newhead,*newtail;
    15. newhead = newtail = NULL;
    16. struct ListNode* cur = head;
    17. while(cur)
    18. {
    19. if(cur->val != val)
    20. {
    21. if(newtail == NULL)
    22. {
    23. newhead = newtail = cur;
    24. }
    25. else
    26. {
    27. newtail->next = cur;
    28. newtail = newtail->next;
    29. }
    30. cur = cur->next;
    31. }
    32. else
    33. {
    34. struct ListNode* next = cur->next;
    35. free(cur);
    36. cur = next;
    37. }
    38. }
    39. if(newtail)
    40. {
    41. newtail->next =NULL;
    42. }
    43. return newhead;
    44. }

    方法二:我们可以遍历链表将val相等的位置直接释放即可。这种方法别的地方也叫做迭代法。

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. struct ListNode* removeElements(struct ListNode* head, int val)
    9. {
    10. while (NULL != head && head->val == val)
    11. {
    12. head = head->next;
    13. }
    14. if (NULL == head)
    15. {
    16. return head;
    17. }
    18. struct ListNode* cur = head;
    19. struct ListNode* prev = head;
    20. while(cur)
    21. {
    22. if(cur->val == val)
    23. {
    24. //找到前一个
    25. while(prev->next->val != val)
    26. {
    27. prev = prev->next;
    28. }
    29. struct ListNode* next = cur->next;
    30. prev->next = next;
    31. free(cur);
    32. cur = next;
    33. }
    34. else
    35. {
    36. cur = cur->next;
    37. }
    38. }
    39. return head;
    40. }

    2、反转链表

    这道题我们先创建一个结构体指针指向链表的头指针然后头插到新的链表头,最后返回新的链表头。

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

     3、返回链表中间节点

    这道题我们可以使用快慢指针的方法,定义两个结构体指针。快指针走两步,慢指针走一步。

     

     对于条件的控制我们应该区分出链表节点个数的奇偶性,当链表节点个数为奇数时fast应不能为空指针,当个数为偶数时fast的next不能为空。

    1. struct ListNode* middleNode(struct ListNode* head)
    2. {
    3. struct ListNode* fast = head;
    4. struct ListNode* slow = head;
    5. while(head&&head->next)
    6. {
    7. head = head->next->next;
    8. slow = slow->next;
    9. }
    10. return slow;
    11. }

     4、返回链表倒数第k个节点

     这道题依旧是快慢指针,但与上一道题不同。我们先让fast指针走k步,然后两个指针同时走。直到fast为空,返回slow。

     

    1. struct ListNode* FindKthToTail(struct ListNode* pListHead, int k )
    2. {
    3. // write code here
    4. if(pListHead == NULL)
    5. {
    6. return NULL;
    7. }
    8. struct ListNode* fast = pListHead;
    9. struct ListNode* slow = pListHead;
    10. while(k)
    11. {
    12. if(fast ==NULL)
    13. return NULL;
    14. fast = fast->next;
    15. k--;
    16. }
    17. while(fast)
    18. {
    19. fast = fast->next;
    20. slow = slow->next;
    21. }
    22. return slow;
    23. }

    5、链表分割

    这道题我们可以利用带哨兵位的头节点来解,malloc两个头节点两个尾节点,一个用来存放大于等于x的节点,一个用来存放小于x的节点。最后将两个链表连起来,再释放掉哨兵位。返回头指针即可。

    1. class Partition {
    2. public:
    3. ListNode* partition(ListNode* pHead, int x)
    4. {
    5. // write code here
    6. struct ListNode* bighead,*bigtail,*littlehead,*littletail;
    7. bighead = bigtail =(struct ListNode*) malloc(sizeof(struct ListNode));
    8. littlehead = littletail =(struct ListNode*) malloc(sizeof(struct ListNode));
    9. struct ListNode* cur = pHead;
    10. while(cur)
    11. {
    12. if(cur->val<x)
    13. {
    14. littletail->next = cur;
    15. littletail = cur;
    16. }
    17. else
    18. {
    19. bigtail->next = cur;
    20. bigtail = cur;
    21. }
    22. cur = cur->next;
    23. }
    24. littletail->next = bighead->next;
    25. bigtail->next = NULL;
    26. pHead = littlehead->next;
    27. free(littlehead);
    28. free(bighead);
    29. return pHead;
    30. }
    31. };

     6、合并链表

     此题我们可以将l2中的节点放入l1中,只需要一个一个比较、插入即可。

    1. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
    2. {
    3. struct ListNode* head1 = NULL;
    4. struct ListNode* tail1 = NULL;
    5. if(list1 == NULL)
    6. {
    7. return list2;
    8. }
    9. if(list2 == NULL)
    10. {
    11. return list1;
    12. }
    13. while(list1&&list2)
    14. {
    15. if(list1->val<list2->val)
    16. {
    17. if(tail1 == NULL)
    18. {
    19. head1 = tail1 = list1;
    20. }
    21. else
    22. {
    23. tail1->next = list1;
    24. tail1 = tail1->next;
    25. }
    26. list1 = list1->next;
    27. }
    28. else
    29. {
    30. if(tail1 == NULL)
    31. {
    32. head1 = tail1 = list2;
    33. }
    34. else
    35. {
    36. tail1->next = list2;
    37. tail1 = tail1->next;
    38. }
    39. list2 = list2->next;
    40. }
    41. }
    42. if(list1)
    43. tail1->next = list1;
    44. if(list2)
    45. tail1->next = list2;
    46. return head1;
    47. }

  • 相关阅读:
    【Spring Boot 源码学习】初识 SpringApplication
    VS2022升级之后,原有项目出现异常
    Mysql 读写分离
    Flex & Bison 开始
    C#开发的OpenRA游戏之金钱系统(3)
    【Python】约瑟夫环问题
    擎创技术流 | Prometheus与Zabbix的融合实践
    【零基础入门MyBatis系列】第十一篇——动态SQL
    【mysql篇-基础篇】通用语法1
    生成学习全景:从基础理论到GANs技术实战
  • 原文地址:https://blog.csdn.net/m0_64334842/article/details/127830266