链表的奇偶重排(C++)

问题描述

给定一个单链表,请设定一个函数,将链表的奇数位节点和偶数位节点分别放在一起,重排后输出。

注意是节点的编号而非节点的数值。

数据范围:节点数量满足 0≤n≤1050≤n≤105,节点中的值都满足 0≤val≤10000≤val≤1000

要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)

示例1

输入:

复制代码
{1,2,3,4,5,6}

返回值:

复制代码
{1,3,5,2,4,6}

说明:

1->2->3->4->5->6->NULL

重排后为

1->3->5->2->4->6->NULL

示例2

输入:

复制代码
{1,4,6,3,7}

返回值:

复制代码
{1,6,7,4,3}

说明:

1->4->6->3->7->NULL

重排后为

1->6->7->4->3->NULL

奇数位节点有1,6,7,偶数位节点有4,3。重排后为1,6,7,4,3

解题思路

设置两个指针,odd指向第一个奇数号节点,even指向第一个偶数号节点,p为新链表的工作指针,先将原链表的所有奇数号节点插入到新链表中(odd指针每次向后走两步),以原节点的值创建新的节点,插入到新链表中,偶数号节点也做同样的处理。最后一个节点要单独处理,如果最后 一个节点是奇数号,则要在处理偶数号节点之前处理完。

代码实现

cpp 复制代码
    ListNode* oddEvenList(ListNode* head) {
        // write code here
        if(head == nullptr || head->next == nullptr) return head;
        ListNode* dummy = new ListNode(-1);
        ListNode* odd = head;
        ListNode* even = head->next;
        ListNode* p = dummy;
        while(odd && odd->next)
        {
            ListNode* tmpnode = new ListNode(odd->val);
            p->next = tmpnode;
            odd = odd->next->next;
            p = p->next;
        }
        if(odd)
        {
            ListNode* tmp = new ListNode(odd->val);
            p->next = tmp;
            p = p->next;
        }
        while(even && even->next)
        {
            ListNode* tmpnode = new ListNode(even->val);
            p->next = tmpnode;
            even = even->next->next;
            p = p->next;
        }
        if(even)
        {
            ListNode* tmp = new ListNode(even->val);
            p->next = tmp;
            p = p->next;
        }
        p->next = nullptr;
        return dummy->next;
    }

代码解析

  1. 条件判断
cpp 复制代码
if (head == nullptr || head->next == nullptr) return head;

如果链表为空或链表中只有一个元素,直接返回原链表。因为对于空链表或单元素链表,奇偶排序不需要做任何操作。

  1. 辅助结点和指针
cpp 复制代码
ListNode* dummy = new ListNode(-1);
ListNode* odd = head;
ListNode* even = head->next;
ListNode* p = dummy;

dummy 是一个辅助节点,它的作用是帮助我们在处理链表时始终能够有一个非空节点来连接奇偶分开的部分,最终返回链表的起始节点。odd 指向链表中的奇数位置的节点,初始化为头节点 headeven 指向链表中的偶数位置的节点,初始化为头节点的下一个节点 head->nextp 是一个游走指针,用来构建新的链表。

  1. 处理奇数位置结点
cpp 复制代码
while (odd && odd->next) {
    ListNode* tmpnode = new ListNode(odd->val);
    p->next = tmpnode;
    odd = odd->next->next;
    p = p->next;
}
if (odd) {
    ListNode* tmp = new ListNode(odd->val);
    p->next = tmp;
    p = p->next;
}

循环用于将链表中的奇数位置的节点按顺序连接起来。如果原链表的奇数部分有最后一个元素(odd 仍然有效),就将它添加到新链表中。

  1. 处理偶数位置结点
cpp 复制代码
while (even && even->next) {
    ListNode* tmpnode = new ListNode(even->val);
    p->next = tmpnode;
    even = even->next->next;
    p = p->next;
}
if (even) {
    ListNode* tmp = new ListNode(even->val);
    p->next = tmp;
    p = p->next;
}

循环用于处理偶数位置节点,基本逻辑与奇数节点的处理类似。如果原链表的偶数部分有最后一个元素(even 仍然有效),就将它添加到新链表中。

总结

代码实现了将链表按照奇偶顺序重新排列的功能。首先,通过两个指针分别提取奇数位置和偶数位置的节点,然后将奇数节点连接成一个链表,再将偶数节点连接成另一个链表。最终,将两个链表合并,返回重新排列后的链表。该方法通过创建新节点并重新连接链表来实现奇偶排序,避免了改变原链表的结构。

相关推荐
第二只羽毛34 分钟前
C++ 高并发内存池1
大数据·开发语言·c++·开源
不想看见40442 分钟前
C++/Qt 实习岗位深度解析【结合一次研发实习谈感受】
开发语言·c++·qt
王老师青少年编程1 小时前
信奥赛C++提高组csp-s之组合数学专题课:鸽巢原理详解及案例实践
c++·组合数学·信奥赛·抽屉原理·csp-s·提高组·鸽巢原理
njidf2 小时前
C++与Qt图形开发
开发语言·c++·算法
ZoeJoy82 小时前
算法筑基(一):排序算法——从冒泡到快排,一文掌握最经典的排序算法
数据结构·算法·排序算法
qwehjk20082 小时前
代码动态生成技术
开发语言·c++·算法
承渊政道2 小时前
【优选算法】(实战体会位运算的逻辑思维)
数据结构·c++·笔记·学习·算法·leetcode·visual studio
m0_716765232 小时前
C++提高编程--STL常用容器(set/multiset、map/multimap容器)详解
java·开发语言·c++·经验分享·学习·青少年编程·visual studio
承渊政道3 小时前
【优选算法】(实战推演模拟算法的蕴含深意)
数据结构·c++·笔记·学习·算法·leetcode·排序算法
朽棘不雕3 小时前
c++中为什么new[]和delete[]要配对使用
c++