题目:原单链表: {L(0), L(1), L(2)..., L(n-2), L(n-1), L(n)}, 重新排序为:{L(0), L(n), L(1), L(n-1), L(2), L(n-2), ..., L(m)}
输入:n( n: [0, 20000])个数字:{L(0), L(1), L(2)..., L(n-2), L(n-1), L(n)}( L(n): [0, 1000] ), 输入顺序即为链表元素顺序。
输出:重排后的链表:{L(0), L(n), L(1), L(n-1), L(2), L(n-2), ..., L(m)}
限制:空间复杂度 O(1), 时间复杂度 O(n)
解题语言:C语言
解题思路:
题目可看成是 对后半部分的结点逆序,逐个插入前半部分的结点中间,则问题拆解成两个问题:1)找链表的中结点位置;2)对后半部分结点逆序重排。
问题1)可利用快慢指针实现;问题2)可利用栈的特性:先入后出;
解题后的心得:
逆序问题可首先考虑栈,空间复杂度和时间复杂度均为最佳。
代码:
1. 变量定义 和 main函数
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int val;
struct ListNode *next;
};
int main(int argc, char *argv[])
{
struct ListNode *pList = NULL;
pList = createList();
reorderList(pList);
printList(pList);
return 0;
}
2. 链表创建和打印输出:
struct ListNode *createList()
{
struct ListNode *pNew = NULL;
struct ListNode *pHead = NULL;
struct ListNode *pEnd = NULL;
unsigned int inputNumCount = 0;
unsigned int inputNumber = 0;
unsigned int count = 0;
printf("please input number count: ");
scanf("%u", &inputNumCount);
if (0 == inputNumCount)
{
return NULL;
}
pHead = NULL;
pEnd = NULL;
count = 0;
while (inputNumCount--)
{
printf("%u: ", count+1);
scanf("%u", &inputNumber);
pNew = (struct ListNode *)malloc(sizeof(struct ListNode));
if (NULL == pNew)
{
printf("malloc node error! inputNumCount: %u\n", inputNumCount);
return pNew;
}
pNew->val = inputNumber;
pNew->next = NULL;
count++;
if (1 == count)
{
pHead = pNew;
pEnd = pNew;
}
else
{
pEnd->next = pNew;
pEnd = pNew;
}
}
return pHead;
}
void printList(struct ListNode *head)
{
struct ListNode *plistNode = NULL;
if (NULL == head)
{
printf("list is NULL\n");
return ;
}
plistNode = head;
while (NULL != plistNode)
{
printf("%d ", plistNode->val);
plistNode = plistNode->next;
}
printf("\n");
return ;
}
3. 重排列表接口:(编码习惯:栈空间最后要销毁,避免内存泄漏)
void reorderList(struct ListNode *head)
{
struct ListNode *pFirstHalfList = NULL;
struct ListNode *pSecondHalfList = NULL;
struct ListNode *pTmpListNode = NULL;
struct ListNode *pFastNode = NULL;
struct ListNode *pSlowNode = NULL;
struct ListNode *pStackTop = NULL;
struct ListNode *pStackBottom = NULL;
struct ListNode *pTmpStackNode = NULL;
if (NULL == head)
{
//printf("list is not exit!\n");
return ;
}
if (NULL == head->next ||
NULL == head->next->next)
{
//printf("list not need sort\n");
return ;
}
/* 快慢指针找 中点 */
pSlowNode = head;
pFastNode = head->next;
while(NULL != pFastNode->next &&
NULL != pFastNode->next->next)
{
pSlowNode = pSlowNode->next;
pFastNode = pFastNode->next->next;
}
/* 链表对半拆开 */
pFirstHalfList = head;
pSecondHalfList = pSlowNode->next;
pSlowNode->next = NULL;
/* 创建栈底结点 */
pStackBottom = (struct ListNode *)malloc(sizeof(struct ListNode));
if (NULL == pStackBottom)
{
printf("creat stack failed!\n");
return ;
}
memset(pStackBottom, 0, sizeof(struct ListNode));
pStackTop = pStackBottom;
/* 后半部分链表入栈 */
while(NULL != pSecondHalfList)
{
pTmpListNode = pSecondHalfList->next;
pSecondHalfList->next = pStackTop;
pStackTop = pSecondHalfList;
pSecondHalfList = pTmpListNode;
}
/* 出栈,并和 前半部分链表重组 */
while (pStackTop != pStackBottom &&
NULL != pFirstHalfList)
{
pTmpListNode = pFirstHalfList;
pTmpStackNode = pStackTop;
pFirstHalfList = pFirstHalfList->next;
pStackTop = pStackTop->next;
pTmpStackNode->next = pTmpListNode->next;
pTmpListNode->next = pTmpStackNode;
}
if (pStackTop != pStackBottom)
{
pTmpStackNode->next = pStackTop;
pStackTop = pStackTop->next;
pTmpStackNode->next->next = NULL;
}
/* 销毁栈,防止内存泄漏 */
while (pStackTop != pStackBottom)
{
pTmpStackNode = pStackTop;
pStackTop = pStackTop->next;
printf("code error!!\n");
free(pTmpStackNode);
}
free(pStackBottom);
return ;
}