LeetCode 328 Odd Even Linked List(奇偶链表)(Linked List)(*)

简介: 版权声明:转载请联系本人,感谢配合!本站地址:http://blog.csdn.net/nomasp https://blog.csdn.net/NoMasp/article/details/50535947 翻译给定一个单链表,将所有的奇节点归为一组,偶节点紧随其后。
版权声明:转载请联系本人,感谢配合!本站地址:http://blog.csdn.net/nomasp https://blog.csdn.net/NoMasp/article/details/50535947

翻译

给定一个单链表,将所有的奇节点归为一组,偶节点紧随其后。

请注意我们现在谈的是奇节点而不是节点上的值。

你应该尝试就地完成。

程序应该在O(1)空间复杂度和O(nodes)时间复杂度下完成。

例如:
给定 1->2->3->4->5->NULL,
返回 1->3->5->2->4->NULL。

注释:
最后归类出来的奇节点和偶节点的相对位置应该和输入时一致。

第一个节点为奇节点,第二个节点为偶节点,以此类推……

原文

Given a singly linked list, group all odd nodes together followed by the even nodes. 

Please note here we are talking about the node number and not the value in the nodes.

You should try to do it in place. 

The program should run in O(1) space complexity and O(nodes) time complexity.

Example:
Given 1->2->3->4->5->NULL,
return 1->3->5->2->4->NULL.

Note:

The relative order inside both the even and odd groups should remain as it was in the input. 

The first node is considered odd, the second node even and so on ...

分析

寒假第一题,农村老家真的超冷……我想的思路可能不是太简洁,再加上考虑的不全面,导致不断的出错、调试、出错、调试……最终花了好久才完成,而代码已经谈不上简洁了。

ListNode* oddEvenList(ListNode* head) {
    if (!head || !head->next) return head;
    bool oddFlag = true;          
    ListNode* odd = head;
    ListNode* even = head->next;
    ListNode* oddHead = odd;
    ListNode* evenHead = even;
    head = head->next->next;      
    while (head) {
        if (oddFlag) {
            odd->next = head;
            odd = odd->next;
            oddFlag = false;
        }
        else {
            even->next = head;
            even = even->next;
            oddFlag = true;
        }
        head = head->next;
    }
    if (!oddFlag)
        even->next = NULL;
    odd->next = evenHead; 
    return oddHead;
}

过程叻大概是这样的:

1,判断是否为空,两种情况都返回head。
2,新建odd和even来不断遍历,和head一样,它们三个是会移动的。
3,oddHead和evenHead是不会动的,用于最后拼凑新的链表。
4,用isOdd来判断当前的节点是否是奇节点,不管是不是,它们的操作都是类似的。
5,最后的时候,如果是奇节点结尾的,那么可能偶节点最后一个会是多余的,所以需要将它干掉。
6,拼凑新的链表用于返回。

然而仔细想想呢,其实还有很大的改善空间,比如说:

既定义了oddHead还定义了evenHead,有一个很好的解决方案是:用head来作为oddHead。这样在返回的时候我们就可以直接返回head了,那么新的问题来了?之前我们是用的head来进行迭代的,那么现在呢?我们需要找到一种新的解决办法。

我们来回顾一下之前的算法:用head来遍历每一个节点,用一个bool变量来标志这个节点的性质(奇节点还是偶节点)。举个例子:

12345NULL

我们发现奇节点的下一个节点恰好就是偶节点的下一个节点(1的下一个节点应该是2的下一个节点,也就是3),而偶节点的下一个节点也恰好是奇节点是下一个节点。这样我们就可以只通过odd和even两个变量来遍历了,既省去了用来遍历的head,也省去了一个变量oddHead,同时还可以直接返回head,何乐而不为呢?

还记得上面我们用了这样一步吗?

if (!isOdd)
    even->next = NULL;
odd->next = evenHead; 

如果按照现在的思路,那么也完全不需要这个判断了,因为在求next的过程中,已经将该用NULL的地方设置成了NULL。

所以代码修改成:

ListNode* oddEvenList(ListNode* head) {
    if (!head) return head;    
    ListNode* odd = head;
    ListNode* even = head->next;
    ListNode* evenHead = even;   
    while (odd->next && even->next) {
        odd->next = even->next;
        odd = odd->next;    
        even->next = odd->next;
        even = even->next;
    }
    odd->next = evenHead;
    return head;
}

while循环中间的部分的顺序可不能颠倒了,只有更新了odd之后,才能将odd->next的设为even->next。

代码

C Plus Plus

/**
* Definition for singly-linked list.
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        if (!head) return head;
        ListNode* odd = head;
        ListNode* even = head->next;
        ListNode* evenHead = even;
        while (odd->next && even->next) {
            odd->next = even->next;
            odd = odd->next;
            even->next = odd->next;
            even = even->next;
        }
        odd->next = evenHead;
        return head;
    }
};

Java

updated at 2016/09/20
    public ListNode oddEvenList(ListNode head) {
        if (head == null) return head;
        ListNode odd = head;
        ListNode even = head.next;
        ListNode evenHead = even;
        while (odd.next != null && even.next != null) {
            odd.next = even.next;
            odd = odd.next;
            even.next = odd.next;
            even = even.next;
        }
        odd.next = evenHead;
        return head;
    }
目录
相关文章
|
5月前
|
索引 Python
【Leetcode刷题Python】328. 奇偶链表
在不使用额外空间的情况下,将链表中的奇数和偶数索引节点重新排序的方法,并提供了相应的Python实现代码。
44 0
|
5月前
|
存储 Java
|
8月前
|
数据采集 Java 数据处理
Java流与链表:探索java.util.stream与LinkedList的交汇点
本文探讨了Java中流(Streams)与链表(LinkedList)的结合使用,展示了如何通过流处理LinkedList以实现高效数据操作。示例代码包括LinkedList的基本操作、使用Stream进行过滤和映射,以及结合HttpClient和代理IP实现网络爬虫。代理IP有助于绕过反爬机制,提高爬取效率。通过结合这些技术,开发者能编写出更简洁、高效的代码。
Java流与链表:探索java.util.stream与LinkedList的交汇点
|
8月前
|
算法 测试技术
【数据结构与算法 | 基础篇】模拟LinkedList实现的双向循环链表
【数据结构与算法 | 基础篇】模拟LinkedList实现的双向循环链表
|
8月前
|
存储 算法 Java
【数据结构与算法 | 基础篇】模拟LinkedList实现的双向链表
【数据结构与算法 | 基础篇】模拟LinkedList实现的双向链表
|
8月前
|
算法
【数据结构与算法 | 基础篇】模拟LinkedList实现的链表(无哨兵)
【数据结构与算法 | 基础篇】模拟LinkedList实现的链表(无哨兵)
|
8月前
|
索引
每日一题:力扣328. 奇偶链表
每日一题:力扣328. 奇偶链表
54 4
|
7月前
|
C++ 容器
【C++进阶】深入STL之list:高效双向链表的使用技巧
【C++进阶】深入STL之list:高效双向链表的使用技巧
74 0
|
8月前
|
存储 Python
链表(Linked List)详解
链表(Linked List)详解
66 0
|
8月前
|
测试技术 C语言
如何用C语言实现无头单向非循环链表Single List ?
这篇文档介绍了一个关于单链表数据结构的实现和相关操作。单链表是一种线性数据结构,每个元素(节点)包含数据和指向下一个节点的指针。文档中列出了单链表的图示,并提供了C语言实现单链表的代码,包括动态申请节点、打印链表、头插、尾插、头删、尾删、查找和在特定位置插入或删除节点等函数。 此外,文档还包含了三个测试用例(TestSList1至TestSList4),展示了如何使用这些函数创建、修改和操作单链表。这些测试用例涵盖了插入、删除、查找等基本操作,以及在链表中特定位置插入和删除节点的场景。
47 0