当前位置:   article > 正文

数据结构链表2(常考习题1)(C语言)

数据结构链表2(常考习题1)(C语言)

移除链表元素:

. - 力扣(LeetCode)

题目:

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

解题思路:

情况1:

情况2:

情况3:

我们以第一种情况写代码:

  1. ListNode* removeElements(ListNode* head, int val)
  2. {
  3. ListNode* cur = head;
  4. ListNode* slow = head;
  5. while (cur)
  6. {
  7. if (cur->val == val)
  8. {
  9. ListNode* tmp = cur->next;
  10. free(cur);
  11. cur = tmp;
  12. slow->next = cur;
  13. }
  14. else
  15. {
  16. slow = cur;
  17. cur = cur->next;
  18. }
  19. }
  20. }

以第二、三种特殊情况改代码:

如果第一次就要删除头:

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

反转链表

. - 力扣(LeetCode)

题目:


给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

解题思路:

考虑特殊:

只有一个元素:

同样适用!! 

        双指针解题,一个前驱指针,一个指向head的指针,还有一个临时变量next为了记录head的next的值。

具体代码如下:

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

链表的中间节点:

. - 力扣(LeetCode)

题目:

        给你单链表的头结点 head ,请你找出并返回链表的中间结点。

        如果有两个中间结点,则返回第二个中间结点。

解题思路:

        利用快慢指针,有四种情况,如图所示:

第一种,链表个数为偶数时:

第二种,链表个数为奇数时:

第三种,链表个数为1个时:

第四种,链表个数为2个时:

综上:

得出结论:
1、当链表个数大于2时,且为偶数时:

当快指针的next走到NULL时,慢指针所在的地方就是中间结点的地方。

2、当链表个数大于2时,且为奇数时:

当快指针走到NULL时,慢指针所在的地方就是中间节点的地方。

3、当链表个数等于1时:

快指针和慢指针不需要走。

4、当链表个数为2时:

和情况一是一样的。

综上:

也就是快指针分两种情况:

第一种就是快指针自身到达NULL时,第二种就是快指针的next到达NULL时。

不论是那种情况,最终都返回慢指针!!

代码如下:

  1. ListNode* middleNode(ListNode* head)
  2. {
  3. ListNode* fast = head;
  4. ListNode* slow = head;
  5. while (fast)
  6. {
  7. if (fast->next == NULL)
  8. {
  9. return slow;
  10. }
  11. fast = fast->next->next;
  12. slow = slow->next;
  13. }
  14. return slow;
  15. }

合并两个有序链表:

. - 力扣(LeetCode)

题目:

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

解题思路:

        两个链表,每个链表都有一个可以移动的指针,接着让一个指针移动,每移一步让两个指针指向的值做对比,小的移下来,然后让新链表的指针和刚刚移动过的俩把表指针往后走一步。

        直到其中一个链表的指针指向空之后,将另一个链表的剩下部分整体移过去!

画图很重要!!!

特殊考虑:

        如果其中一个链表为空,可以指直接返回另一个链表的地址!

代码如下:

画图很重要!!!!!!

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

链表分割:

链表分割_牛客题霸_牛客网

题目:

        现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

解题思路:

        将比x大的和比x小的首先区分开,最后再将其合并在一起!!

注意:最后比x大的后面需要手动在末尾添加NULL指针!


考虑特殊:

        如果链表中没有比x大的数,或者没有比x小的数,此时直接返回原链表的地址!!

代码如下:
 

  1. ListNode* partition(ListNode* pHead, int x)
  2. {
  3. ListNode* cur = pHead;
  4. ListNode* newhead1 = NULL;
  5. ListNode* tmp1 = NULL;
  6. ListNode* newhead2 = NULL;
  7. ListNode* tmp2 = NULL;
  8. while (cur)
  9. {
  10. if (cur->val > x)
  11. {
  12. if (newhead1 == NULL)
  13. {
  14. newhead1 = tmp1 = cur;
  15. }
  16. else
  17. {
  18. tmp1->next = cur;
  19. tmp1 = tmp1->next;
  20. }
  21. }
  22. else
  23. {
  24. if (newhead2 == NULL)
  25. {
  26. newhead2 = tmp2 = cur;
  27. }
  28. else
  29. {
  30. tmp2->next = cur;
  31. tmp2 = tmp2->next;
  32. }
  33. }
  34. cur = cur->next;
  35. }
  36. if (!(newhead1 && newhead2))
  37. {
  38. return pHead;
  39. }
  40. tmp1->next = NULL;
  41. tmp2->next = newhead1;
  42. return newhead2;
  43. }

链表的回文结构:

链表的回文结构_牛客题霸_牛客网

题目:

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

测试样例:

1->2->2->1
返回:true

解题思路:

        文字叙述:


        只需要将该链表进行反转后,然后两个链表进行遍历,如果中途有不一样的值就输出fasle

如果遍历结束后,两个指针都指向NULL,返回true,就可以说明该链表是回文结构。

具体代码:
        

  1. ListNode* Reverse(ListNode*head)//链表反转代码
  2. {
  3. ListNode* cur = head;
  4. ListNode* slow = NULL;
  5. while (cur)
  6. {
  7. ListNode* tmp = cur->next;
  8. cur->next = slow;
  9. slow = cur;
  10. cur = tmp;
  11. }
  12. return slow;
  13. }
  14. bool chkPalindrome(ListNode* pHead) //判断回文代码
  15. {
  16. ListNode* cur = pHead;
  17. ListNode* newhead = NULL;
  18. newhead = Reverse(cur);
  19. while (cur&&newhead)
  20. {
  21. if(cur->val != newhead->val)
  22. {
  23. return false;
  24. }
  25. cur = cur->next;
  26. newhead = newhead->next;
  27. }
  28. return true;
  29. // write code here
  30. }

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号