当前位置:   article > 正文

143. 重排链表 步骤分解_重排链表的调试步骤

重排链表的调试步骤

题目:

给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:

给定链表 1->2->3->4, 重新排列为 1->4->2->3.
示例 2:

给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.

解题分析:

      当链表节点数在两个以内时,无需重排;达到的效果是将链表右边比较大的一半链表倒序逐个插入左边里。可以将思路整理为这么几部分:

1:找出链表中间节点,在合适的地方链表截断。

      中间节点之后的节点都是需要向左边插入的。如果纠结这个奇偶问题,可以就示例用快慢指针走一下,就会发现,slow->next就是需要择出来插左边的头结点。为描述方便,这里称右边需要拎出来的链表为大数链表,左边为小数链表。毫无疑问,大数链表比小数链表短

2:按照题意,重排后,大数链表是倒序插入左边的,所以找出大数链表后,需要对大数链表进行翻转。

3:如果大数链表还有需要处理的节点,则向小数链表内间隔地插入节点。

解法1:纯链表操作

  1. class Solution {
  2. private:
  3. ListNode* findMidNode(ListNode* head) { //找中间节点
  4. ListNode *fast = head, *slow = head;
  5. while (fast && fast->next) {
  6. slow = slow->next;
  7. fast = fast->next->next;
  8. }
  9. return slow;
  10. }
  11. ListNode* reverseList(ListNode* head) { //翻转链表
  12. ListNode *former = head, *latter = NULL;
  13. while (head) {
  14. head = head->next;
  15. former->next = latter;
  16. latter = former;
  17. former = head;
  18. }
  19. return latter;
  20. }
  21. public:
  22. void reorderList(ListNode* head) {
  23. if (NULL == head || NULL == head->next
  24. || NULL == head->next->next) //两个节点以内
  25. return;
  26. ListNode *ptr = findMidNode(head); //找到链表中点
  27. ListNode *bigHead = ptr->next; //断掉小数链表和大数链表
  28. ptr->next = NULL;
  29. bigHead = reverseList(bigHead); //翻转大数链表
  30. ptr = head;
  31. ListNode *former = head->next;
  32. while (bigHead) { //向小数链表里插大数节点
  33. ptr->next = bigHead;
  34. bigHead = bigHead->next;
  35. ptr->next->next = former;
  36. ptr = ptr->next->next;
  37. former = former->next;
  38. }
  39. }
  40. };

          如果想让指针的命名直接易懂,不封装函数真的很难做到,不然就为起个贴切的好名字声明一堆指针就太浪费空间了。

解法2:空间换时间

         将所有节点放入数组里,利用数组的下标直接对节点进行访问。

解法3:找到中间链表后,用栈代替翻转

         用栈的先进后出处理大数链表,自然可以先找到最大数的节点,这样就不用翻转大数链表了。

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/226754
推荐阅读
相关标签
  

闽ICP备14008679号