力扣143. 重排链表(栈、插入链表)
https://leetcode-cn.com/problems/reorder-list/
给定一个单链表 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.
复杂度分析
时间复杂度:O(n)
空间复杂度:O(n),最坏情况是O(n/2),一半节点压栈
三个步骤:
- 首先重新排列后,链表的中心节点会变为最后一个节点。所以需要先找到链表的中心节点
-
以按照中心节点将原始链表划分。
2.1. 按照中心节点将原始链表划分,中心节点前链表不变:1->2->3
2.2. 中心节点后链表压栈,出栈时实现反转,就正好是重排链表交换的顺序:5->4。 -
先原链表插入栈顶元素,即可重新排列成:1->5->2->4->3.
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution
{
public:
void reorderList(ListNode* head)
{
//鲁棒性
if (head == nullptr)return;
//得到链表长度
int len = 0;
ListNode* templen = head;
while (templen != nullptr)
{
len++;
templen = templen->next;
}
//新链表的最后一个节点
ListNode* p = head;
for (int i = 1; i <= (len / 2); i++)
{
p = p->next;
};
//把新链表的最后一个节点后面的节点压紧栈中
stack<ListNode*>sta;
while (p->next != nullptr)
{
sta.push(p->next);
p->next = p->next->next;
}
//出栈时隔一个插进链表
while (!sta.empty())
{
ListNode* temp = sta.top();
sta.pop();
temp->next = head->next;
head->next = temp;
head = head->next->next;
}
}
};
int main()
{
ListNode head[5] = { 1,2,3,4,5 };
head[0].next = &head[1];
head[1].next = &head[2];
head[2].next = &head[3];
head[3].next = &head[4];
//head[4].next = &head[5];
Solution s;
s.reorderList(head);
return 0;
}