刷题(牛客网)NC2 重排链表

题目:原单链表: {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 ;    
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值