排序奇升偶降链表

题目描述 : 给定一个奇数位升序,偶数位降序的链表,将其重新排序。

输入: 1->8->3->6->5->4->7->2->NULL
输出: 1->2->3->4->5->6->7->8->NULL

要求: 时间复杂度为O(N),空间复杂度O(1)。

思路:

1. 按奇偶位置拆分链表,得1->3->5->7->NULL和8->6->4->2->NULL

2. 反转偶链表,得1->3->5->7->NULL和2->4->6->8->NULL

3. 合并两个有序链表,得1->2->3->4->5->6->7->8->NULL

代码:

class Solution {
    /**
     * 1. 拆分奇偶链表
     * 2. 翻转偶数链表
     * 3. 合并有序链表
     */
    public static ListNode sortList(ListNode list) {
        // 1. 拆分奇偶链表
        ListNode[] arr = separate(list);
        // 2. 翻转偶数链表
        ListNode oddList = arr[0];
        ListNode evenList = reverse(arr[1]);
        // 3. 合并有序链表
        return mergeSortedLists(oddList, evenList);
    }

    private static ListNode mergeSortedLists(ListNode oddList, ListNode evenList) {
        ListNode dummyNode=new ListNode();
        ListNode cur=dummyNode;
        while(oddList!=null || evenList!=null){
            if(oddList!=null){
                cur.next=oddList;
                oddList=oddList.next;
                cur=cur.next;
                cur.next=null;
            }
            if(evenList!=null){
                cur.next=evenList;
                evenList=evenList.next;
                cur=cur.next;
                cur.next=null;
            }
        }
        return dummyNode.next;
    }

    private static ListNode reverse(ListNode listNode) {
        if(listNode==null || listNode.next==null) return listNode;
        ListNode newHead=reverse(listNode.next);
        listNode.next.next=listNode;
        listNode.next=null;
        return newHead;
    }

    private static ListNode[] separate(ListNode list) {
        if (list == null || list.next == null) return new ListNode[]{list, null};
        ListNode dummyNode = new ListNode();
        ListNode cur = dummyNode;
        ListNode p = list;
        while(p!=null && p.next!=null){
            cur.next=p.next;
            cur=cur.next;
            p.next=p.next.next;
            p=p.next;
            cur.next=null;
        }
        return new ListNode[]{list,dummyNode.next};
    }

    public static void main(String[] args) {
        ListNode listNode = sortList(new ListNode(1, new ListNode(8, new ListNode(3, new ListNode(6, new ListNode(5,
                new ListNode(4, new ListNode(7, new ListNode(2)))))))));
        System.out.println(listNode);
    }
}

感谢大佬 @chenchen4396 提供的优化思路:

  • 直接记住第一个和第二个节点的位置,遇到奇数插在头节点后面,偶数插在尾节点前面

class Solution {
    /**
     * 1. 记住前两个节点,奇数尾插,偶数头插
     * 2. 合并有序链表
     */
    public static ListNode sortList(ListNode list) {
        // 1. 链表小于两个节点,直接返回
        if (list == null || list.next == null) return null;
        // 2. 记住前两个节点,奇数尾插,偶数头插
        ListNode oddList = new ListNode(), cur = oddList;
        ListNode evenList = null;
        int i = 1;
        while (list != null) {
            if ((i++) % 2 == 1) {
                cur.next = list;
                cur = cur.next;
                list = list.next;
                cur.next = null;
            } else {
                ListNode next = list.next;
                list.next = evenList;
                evenList = list;
                list = next;
            }
        }
        // 3. 合并有序链表
        return mergeSortedLists(oddList.next, evenList);
    }

    private static ListNode mergeSortedLists(ListNode oddList, ListNode evenList) {
        ListNode dummyNode = new ListNode();
        ListNode cur = dummyNode;
        while (oddList != null || evenList != null) {
            if (oddList != null) {
                cur.next = oddList;
                oddList = oddList.next;
                cur = cur.next;
                cur.next = null;
            }
            if (evenList != null) {
                cur.next = evenList;
                evenList = evenList.next;
                cur = cur.next;
                cur.next = null;
            }
        }
        return dummyNode.next;
    }

    public static void main(String[] args) {
        ListNode listNode = sortList(new ListNode(1, new ListNode(8, new ListNode(3, new ListNode(6, new ListNode(5,
                new ListNode(4, new ListNode(7, new ListNode(2)))))))));
        System.out.println(listNode);
    }
}

全部评论
感觉是不是有点想复杂了,直接记住第一个和第二个节点的位置,遇到奇数插在头节点后面,偶数插在尾节点前面,是不是就可以了
点赞 回复 分享
发布于 2023-10-19 18:30 浙江

相关推荐

秋招结束已经一段时间了 一直在忙着毕业的事情 浅浅总结一下自己的秋招经历吧~本人BG双非硕 后端选手 有一段小厂+腾讯暑期实习腾讯暑期转正loser秋招结束已经结束了有一段时间了总结一下秋招历程最大的感受就是秋招比起暑期更加卡学历秋招总共投了60多家吧一直面 一直挂也投了两家银行科技岗 都走到终面体检了都拒了(总体感觉本地的银行还是挺容易过的)可能本人更想去私企 并且银行也挺卷听说一直到11月就只有一家小厂的offer并签约当保底然后也突然被WXG捞了 本来都不对腾讯抱有希望了可能经过一整个秋招的面试积累吧 以及本人有ACM经历 WXG整体面试以做题偏多(一二面做了5道题 4道hard) 比较合自己胃口 差不多半个月就把五轮面试过了进入录用评估 但也一直没有结果到后面也陆陆续续有几家中厂也终面过泡池子一直到12月初华子给开了base杭州 14a因为华子公积金的原因 和小厂薪资上差距不大 所以也一直犹豫是否毁约签华子 但是内心也还对WXG抱有一丝幻想(虽然一直没有保温也没有任何消息)然后一直到12月中下旬 华子要求去现场签约了 但是WXG还是没有消息 然后就连续发邮件和打电话催了好多次 还是回复耐心等待直到华子签约那天 经过内心挣扎已经决定毁约签华子了 可能还是想平台更大一点吧 然后最戏剧性的一幕来了 就在我发毁约邮件没有5秒 WXG打电话开奖了 并且开奖也十分有诚意 最终还是没有签约成功华子 研究生期间也打了很多次华子的比赛还是对华子有感情的555整个秋招都是伴随着焦虑的 我认为自己也是秋招大部分人的画像 屡屡碰壁后不断怀疑自己 但是可能自己也比较幸运吧 但是也感谢自己在一次次陷入迷茫都没有放弃自己 还是一直努力背八股 刷题也祝各位牛友们共勉 就算暂时没有好的offer 不放弃一定会有好的结果的!!
点赞 评论 收藏
分享
评论
点赞
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务