字节高频笔试题 奇偶链表排序

本文介绍了一种针对特殊排列的单链表(奇数位置升序、偶数位置降序)进行排序的方法。通过三个步骤:拆分奇偶链表、反转偶数链表、合并两个已排序链表,实现了链表元素的整体升序排列。

题目:

单链表,奇数位置升序,偶数位置降序,如何实现链表从小到大排列?

例: 1->4->3->2->5
输出: 1->2->3->4->5

解法:三部分

1. 拆分奇偶链表
2. 偶链表反转
3. 有序链表合并

代码:

#include<iostream>
using namespace std;
struct ListNode
{
	int value;
	ListNode *next;
};


void addNode(ListNode **head, int value)
{
    ListNode *newNode = new ListNode();
    newNode->value = value;
    newNode->next = NULL;

    if(*head == NULL)
    {
        *head = newNode;
    }
    else
    {
        ListNode *node = *head;
        while(node->next)
        {
            node = node->next;
        }
        node->next = newNode;
    }

}

class Solu
{
public:
    ListNode* mergeOddEven(ListNode* head)
    {
        // 1. 拆分odd even
        if(head == nullptr) return nullptr;

        // 拆分为odd 和 even两个链表
        // odd链表的表头 oddHead
        // even链表的表头:evenHead
        auto odd = head, even = head->next;
        auto oddHead = head, evenHead = head->next;
        while(even && even->next)
        {
            odd->next = even->next;
            odd = odd->next;
            even->next = odd->next;
            even = even->next;
        }

        // 2. 对于even 偶链表做一个链表翻转
        // 因为 even链表是降序的
        ListNode* cur = evenHead, *prev = nullptr;
        ListNode *newHead = nullptr;
        // 印象里反转链表,需要一个prev,cur,newHead
        while(cur)
        {
            if(cur->next == nullptr) newHead = cur;
            ListNode *temp = cur->next;
            cur->next = prev;
            prev = cur;
            cur = temp;
        }
        evenHead = newHead;

        // 3. 两链表合并
        // 不是在原地合并
        // 按序合并
        ListNode* mergeNode = nullptr, *node = nullptr;
        int i = 0;
        while(oddHead && evenHead)
        {
            ListNode *tempNode = new ListNode();
            if(node) {
                node->next = tempNode;
                node = tempNode;
            }

            if(i == 0)
            {
                mergeNode = tempNode;
                node = tempNode;

            }
            i++;

            if(oddHead->value > evenHead->value)
            {
                tempNode->value = evenHead->value;
                evenHead = evenHead->next;
            }
            else
            {
                tempNode->value = oddHead->value;
                oddHead = oddHead->next;
            }

        }

        if(evenHead)
        {
            ListNode *tempNode = new ListNode();
            node->next = tempNode;
            node = node->next;
            node->value = evenHead->value;
            evenHead = evenHead->next;

        }


        if(oddHead)
        {
            ListNode *tempNode = new ListNode();
            node->next = tempNode;
            node = node->next;
            node->value = oddHead->value;
            oddHead = oddHead->next;

        }
        return mergeNode;

    }

};

int main()
{
    ListNode* head = new ListNode(1);

    addNode(&head, 4);

    addNode(&head, 3);

    addNode(&head, 2);

    addNode(&head, 5);

//    while(head)
//    {
//        cout<<head->value<<endl;
//        head = head->next;
//    }

    Solu s;
    head = s.mergeOddEven(head);

    while(head)
    {
        cout<<head->value<<endl;
        head = head->next;
    }

    return 0;

}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值