leetcode链表--4、reorder-list(重新排序单链表)

题目描述
 
Given a singly linked list LL0L1→…→Ln-1Ln,reorder it to: L0LnL1Ln-1L2Ln-2→…
You must do this in-place without altering the nodes' values.
For example,Given{1,2,3,4}, reorder it to{1,4,2,3}.
解题思路:本题的意思是要讲链表重新排序
(比较取巧的方法)
解法一:先将链表放入vector中,然后通过两个指针,一个指向第一个结点,一个指向最后结点,然后将第一个结点指向最后一个结点,然后最后一个结点指向第二个结点,然后进行下一次操作
 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     void reorderList(ListNode *head) {
12       // write your code here
13         if (head == NULL)
14             return;
15          
16         vector<ListNode*> nodes;
17         ListNode* iter = head;
18         while(iter != NULL)
19         {
20             nodes.push_back(iter);
21             iter = iter->next;
22         }
23          
24         int LEN = nodes.size();
25         int left = 0;
26         int right = LEN -1;
27         while(left < right)
28         {
29             nodes[left]->next = nodes[right];
30             nodes[right--]->next = nodes[++left];
31         }
32         nodes[left]->next = NULL;  
33     }
34 };
解法二:理想情况下,如果能一个指针从后往前走,一个指针从前往后走,然后一个一个合并就行了。但是单链表并没有从后往前走的能力,难道要改造成双链表吗?其实不用,我们只要把后半部分反转一下,变成两个链表就行了。要找到后半部分的起点,就是用快慢指针。从头开始,快指针走两步,慢指针走一步,这样快指针到头的时候慢指针就是中间了。不过该题我们不能直接拿到中间,而是要拿到中间的前一个节点,这样才能把第一个子链表的末尾置为空,这里的技巧就是快慢指针循环的条件是fast.next != null && fast.next.next != null。
 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     void reorderList(ListNode *head)
12     {
13         if(head == NULL)
14             return;
15         ListNode *slow = head;
16         ListNode *fast = head;
17         // 找到中点的前一个节点
18         while(fast->next != NULL && fast->next->next != NULL)
19         {
20             fast = fast->next->next;
21             slow = slow->next;
22         }
23         // 反转中点及之后的链表
24         ListNode *head2 = reverseList(slow->next);
25         // 将前半部分链表的末尾置空
26         slow->next = NULL;
27         // 找到两个子链表的头,准备开始合并
28         ListNode *head1 = head;
29         ListNode dummy(0); //创建结构体dummy(0)为l的辅助空间,因为可能在最开始插入
30         ListNode *curr = &dummy;
31         // 当子链表都不为空的时候依次合并
32         while(head2 != NULL && head1 != NULL)
33         {
34             curr->next = head1;
35             head1 = head1->next;
36             curr = curr->next;
37             curr->next = head2;
38             head2 = head2->next;
39             curr = curr->next;
40         }
41         // 当其中一个子链表为空时,把另一个链表剩下的那个节点加上,因为可能一共有奇数个节点
42         curr->next = head2 != NULL ? head2 : NULL;
43         curr->next = head1 != NULL ? head1 : NULL;
44         head = dummy.next;
45     }
46     //迭代反转链表
47     ListNode *reverseList(ListNode *head){
48         if(head == NULL || head->next == NULL)
49         {
50             return head;
51         }
52         ListNode *p1 = head;
53         ListNode *p2 = head->next;
54         while(p2 != NULL)
55         {
56             ListNode *tmp = p2->next;
57             p2->next = p1;
58             p1 = p2;
59             p2 = tmp;
60         }
61         head->next = NULL;
62         return p1;
63     }
64 };

 

转载于:https://www.cnblogs.com/qqky/p/6813169.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值