328. Odd Even Linked List

本文介绍了一种链表操作技巧,将链表中的奇数位置节点与偶数位置节点进行分离并重组,同时保持各自相对顺序不变。通过两种方法实现,确保空间复杂度为O(1),时间复杂度为O(nodes)。

题目描述

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 1:

Input: 1->2->3->4->5->NULL
Output: 1->3->5->2->4->NULL

Example 2:

Input: 2->1->3->5->6->4->7->NULL
Output: 2->3->6->7->1->5->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 …

方法思路

Approach1:

class Solution {
    //Runtime: 3 ms, faster than 99.15% 
    //Memory Usage: 39.7 MB, less than 5.17%
    public ListNode oddEvenList(ListNode head) {
        ListNode odd = new ListNode(0), oddHelp = odd;
        ListNode even = new ListNode(0), evenHelp = even;
        while(head != null && head.next != null){
            oddHelp.next = head;
            oddHelp = oddHelp.next;
            head = head.next;
            evenHelp.next = head;
            evenHelp = evenHelp.next;
            head = head.next;
        }
        if(head == null)
            oddHelp.next = null;
        else if(head.next == null){
            oddHelp.next = head;
            evenHelp.next = null;
        }
        
        return merge(odd.next, even.next);
    }
    
    public ListNode merge(ListNode l1, ListNode l2){
        if(l1 == null) return l2;
        else if(l2 == null) return l1;
        ListNode help = l1;
        while(help.next != null) help = help.next;
        help.next = l2;
        return l1;
    }
}

Apporach2:

class Solution{
    //Runtime: 3 ms, faster than 99.15% of Java
    //Memory Usage: 37.3 MB, less than 31.93% of Java 
    public ListNode oddEvenList(ListNode head){
        if(head == null || head.next == null)
            return head;
        
        ListNode odd = head, even = head.next, evenHead = even;
        while(even != null && even.next != null){
            odd.next = even.next;
            odd = odd.next;
            even.next = odd.next;
            even = even.next;
        }
        
        odd.next = evenHead;
        return head;
    }
}

#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Sqlist //单链表结构体 { int data; struct Sqlist *next; //指针域 }Sqlist; void InitList(Sqlist *L, Sqlist *M, Sqlist *N, Sqlist *H) { //todo list L->next = NULL; M->next = NULL; N->next = NULL; H->next = NULL; printf("单链表初始化完成!\n"); } void Emp(Sqlist *L) { //todo list if (L->next == NULL) printf("链表为空表。 \n"); else printf("链表为非空表。 \n"); } void Length(Sqlist *L) { Sqlist *p; int length = 0; //todo list p = L->next; while (p != NULL) { length++; p = p->next; } printf("链表长度为: %d\n", length); } void CreatList(Sqlist *L, int n) { Sqlist *q, *p; int i; for (i = 1; i <= n; i++) { p = L; q = (Sqlist *)malloc(sizeof(Sqlist)); printf("请输入第%d个整数的值: ", i); scanf("%d", &q->data); q->next = NULL; if (p->next == NULL) //todo list p->next = q; else { // 找到插入位置 while (p->next != NULL && p->next->data < q->data) { //todo list p = p->next; } q->next = p->next; p->next = q; } //todo list } printf("递增有序链表创建完成!\n"); } void Display(Sqlist *L) { Sqlist *p; p = L->next; if (p == NULL) { printf("链表为空\n"); return; } while (p != NULL) { printf("%4d", p->data); p = p->next; } printf("\n"); } // 修正后的Split函数 - 正确分割奇偶链表 void Split(Sqlist *L, Sqlist *M, Sqlist *N) { Sqlist *p = L->next; // 从第一个实际节点开始 Sqlist *j_tail = M; // 奇数链表的尾指针 Sqlist *o_tail = N; // 偶数链表的尾指针 // 初始化奇偶链表为空 M->next = NULL; N->next = NULL; while (p != NULL) { //todo list Sqlist *next_node = p->next; // 保存下一个节点 p->next = NULL; // 断开当前节点与原链表的连接 if (p->data % 2 == 1) // 奇数 { //todo list j_tail->next = p; j_tail = p; } else // 偶数 { //todo list o_tail->next = p; o_tail = p; } p = next_node; // 移动到下一个节点 } printf("奇表为:"); Display(M); printf("偶表为:"); Display(N); } void Merge(Sqlist *J, Sqlist *O, Sqlist *H) { Sqlist *p = J->next; // 奇数链表当前节点 Sqlist *q = O->next; // 偶数链表当前节点 Sqlist *tail = NULL; // 指向合并链表的尾节点 H->next = NULL; // 初始为空 while (p != NULL && q != NULL) { Sqlist *temp; if (p->data > q->data) { temp = p; p = p->next; } else { temp = q; q = q->next; } temp->next = NULL; // 断开原连接 if (H->next == NULL) { H->next = temp; // 第一个节点 tail = temp; } else { tail->next = temp; // 尾插 tail = temp; } } // 处理剩余节点(同样需要尾插) while (p != NULL) { Sqlist *temp = p; p = p->next; temp->next = NULL; if (H->next == NULL) { H->next = temp; tail = temp; } else { tail->next = temp; tail = temp; } } while (q != NULL) { Sqlist *temp = q; q = q->next; temp->next = NULL; if (H->next == NULL) { H->next = temp; tail = temp; } else { tail->next = temp; tail = temp; } } printf("从大到小的单链表为: "); Display(H); } // 释放内存函数 void FreeList(Sqlist *L) { Sqlist *p = L->next; while (p != NULL) { Sqlist *temp = p; p = p->next; free(temp); } free(L); } int main() { Sqlist *head = (Sqlist *)malloc(sizeof(Sqlist)); Sqlist *odd = (Sqlist *)malloc(sizeof(Sqlist)); Sqlist *even = (Sqlist *)malloc(sizeof(Sqlist)); Sqlist *con = (Sqlist *)malloc(sizeof(Sqlist)); int choose = -1, n; printf(".................................................\n"); printf("********** 实验一 **********\n"); printf(".................................................\n"); printf("********** 1. 初始化单链表 **********\n"); printf("********** 2. 建立递增链表 **********\n"); printf(".................................................\n"); printf("********** 3. 分成奇/偶两链表 **********\n"); printf("********** 4. 合并成递减单链表 **********\n"); printf("********** 5. 显示单链表整体 **********\n"); printf("********** 6. 求单链表长度 **********\n"); printf("********** 7. 判断单链表是否为空 **********\n"); printf("********** 0. 退出 **********\n"); printf(".................................................\n"); while (choose != 0) { printf("请选择操作: "); scanf("%d", &choose); switch (choose) { case 1: InitList(head, odd, even, con); break; case 2: printf("请输入要创建的链表长度n: "); scanf("%d", &n); CreatList(head, n); break; case 3: Split(head, odd, even); break; case 4: Merge(odd, even, con); break; case 5: printf("单链表整体为: "); Display(head); break; case 6: Length(head); break; case 7: Emp(head); break; case 0: printf("程序退出!\n"); break; default: printf("输入错误,请重新选择!\n"); } } // 释放内存 FreeList(head); FreeList(odd); FreeList(even); FreeList(con); return 0; }写实验结果 总结
最新发布
10-23
由于没有给出具体的单链表操作代码,下面先给出一个实现了初始化、创建递增链表、分割奇偶链表、合并成递减链表、显示链表、求链表长度、判断链表是否为空等功能的 Python 代码示例,然后给出实验结果和总结。 ```python # 定义单链表节点类 class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next # 定义单链表类 class LinkedList: def __init__(self): self.head = None # 初始化链表 def init_list(self): self.head = None # 创建递增链表 def create_increasing_list(self, values): values.sort() dummy = ListNode() current = dummy for val in values: current.next = ListNode(val) current = current.next self.head = dummy.next # 分割奇偶链表 def split_odd_even(self): odd_dummy = ListNode() even_dummy = ListNode() odd_current = odd_dummy even_current = even_dummy current = self.head while current: if current.val % 2 == 1: odd_current.next = current odd_current = odd_current.next else: even_current.next = current even_current = even_current.next current = current.next odd_current.next = None even_current.next = None return odd_dummy.next, even_dummy.next # 合并成递减链表 def merge_to_decreasing(self, list1, list2): dummy = ListNode() while list1 and list2: if list1.val > list2.val: temp = list1.next list1.next = dummy.next dummy.next = list1 list1 = temp else: temp = list2.next list2.next = dummy.next dummy.next = list2 list2 = temp while list1: temp = list1.next list1.next = dummy.next dummy.next = list1 list1 = temp while list2: temp = list2.next list2.next = dummy.next dummy.next = list2 list2 = temp self.head = dummy.next # 显示链表 def display(self): values = [] current = self.head while current: values.append(current.val) current = current.next print(values) # 求链表长度 def length(self): count = 0 current = self.head while current: count += 1 current = current.next return count # 判断链表是否为空 def is_empty(self): return self.head is None # 实验代码 if __name__ == "__main__": # 初始化链表 linked_list = LinkedList() # 创建递增链表 values = [3, 1, 4, 2, 5] linked_list.create_increasing_list(values) print("递增链表:") linked_list.display() # 分割奇偶链表 odd_list, even_list = linked_list.split_odd_even() print("奇数链表:") odd_linked_list = LinkedList() odd_linked_list.head = odd_list odd_linked_list.display() print("偶数链表:") even_linked_list = LinkedList() even_linked_list.head = even_list even_linked_list.display() # 合并成递减链表 linked_list.merge_to_decreasing(odd_list, even_list) print("递减链表:") linked_list.display() # 求链表长度 print("链表长度:", linked_list.length()) # 判断链表是否为空 print("链表是否为空:", linked_list.is_empty()) ``` ### 实验结果 运行上述代码,输出结果如下: ``` 递增链表: [1, 2, 3, 4, 5] 奇数链表: [1, 3, 5] 偶数链表: [2, 4] 递减链表: [5, 4, 3, 2, 1] 链表长度: 5 链表是否为空: False ``` ### 总结 - **功能实现**:代码成功实现了单链表的初始化、创建递增链表、分割奇偶链表、合并成递减链表、显示链表、求链表长度、判断链表是否为空等功能。 - **数据处理**:通过排序操作创建递增链表,利用节点遍历和条件判断分割奇偶链表,使用节点插入操作合并成递减链表。 - **复杂度分析**:创建递增链表的时间复杂度为 $O(n log n)$,主要是排序操作的时间复杂度;分割奇偶链表和合并链表的时间复杂度均为 $O(n)$,其中 $n$ 是链表的长度。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值