328. 奇偶链表
题目来源:力扣(LeetCode)https://leetcode-cn.com/problems/odd-even-linked-list/
题目
给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。
示例 1:
输入: 1->2->3->4->5->NULL
输出: 1->3->5->2->4->NULL
示例 2:
输入: 2->1->3->5->6->4->7->NULL
输出: 2->3->6->7->1->5->4->NULL
说明:
- 应当保持奇数节点和偶数节点的相对顺序。
- 链表的第一个节点视为奇数节点,第二个节点视为偶数节点,以此类推。
解题思路
思路:分离、合并
先审题,题目给定单链表,要求将所有的奇数节点与偶数节点分别排在一起。
其中这里的奇偶节点并不是指节点的值,而是节点所处的位置奇偶。规定第一个节点为奇数节点,第二个节点视为偶数节点,以此类推。
题目要求使用原地算法,算法空间复杂度为 O ( 1 ) O(1) O(1),时间复杂度为 O ( n ) O(n) O(n)(其中 n 表示 nodes 的节点总数)
现在,可以知道,题目中已经明确定义了奇偶节点,现在是要将奇偶节点分别排在一起。
那么我们可以先考虑将奇偶节点进行分离,分成奇数链表与偶数链表,然后将偶数链表拼接在奇数链表后面,最后返回。
这里说一下具体的思路:
- 这里要先处理特殊情况,如果 h e a d head head 为空,直接返回 h e a d head head;
- 定义奇数链表头节点 o d d odd odd,初始等于 h e a d head head;偶数链表头结点 e v e n even even,初始等于 h e a d . n e x t head.next head.next。这里注意,定义变量 e v e n _ h e a d even\_head even_head 存储偶数头结点,防止指针丢失;
- 维护
o
d
d
odd
odd、
e
v
e
n
even
even,遍历原链表,将链表分离为奇数链表和偶数链表,具体的做法如下:
- 处理奇数节点,此时奇数节点的下一个节点需要指向偶数节点的下一个节点,所以令 o d d . n e x t = e v e n . n e x t odd.next = even.next odd.next=even.next,再令 o d d = o d d . n e x t odd=odd.next odd=odd.next ,等待后续继续分离,而此时 o d d odd odd 在 e v e n even even 的下一个节点;
- 处理偶数节点,此时偶数节点的下一个节点需要指向奇数节点的下一个节点,上面的步骤中, o d d odd odd 已经在 e v e n even even 的下一个节点,那么令 e v e n . n e x t = o d d . n e x t even.next = odd.next even.next=odd.next,再更新 e v e n even even,令 e v e n = e v e n . n e x t even = even.next even=even.next,此时 e v e n even even 在 o d d odd odd 的下一个节点。
- 重复上面的步骤,直到所有节点都被分离在奇数链表和偶数链表中。这里终止的条件是 e v e n even even 或者 e v e n . n e x t even.next even.next 为空时,而此时 o d d odd odd 指向是奇数链表的最后一个节点;
- 最后将偶数链表拼接在奇数链表之后,即是令 o d d . n e x t = e v e n _ h e a d odd.next = even\_head odd.next=even_head。
具体的代码实现如下。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def oddEvenList(self, head: ListNode) -> ListNode:
# 特殊情况处理
if not head:
return head
# 这里保存偶数链表的头结点,用于后续拼接,防止指针丢失
even_head = head.next
# 先分别定义奇偶节点的头结点
odd = head
even = even_head
# 分离
while even and even.next:
odd.next = even.next
odd = odd.next
even.next = odd.next
even = even.next
# 合并
odd.next = even_head
return head
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n), n n n 为节点总数。
- 空间复杂度: O ( 1 ) O(1) O(1)。
欢迎关注
公众号 【书所集录】
如有错误,烦请指出,欢迎指点交流。