<LeetCode(Java版)>Reorder List

本文探讨了如何在不修改节点值的情况下,重新组织单链表,并提供了两种优化方案。第一种利用栈缓存所有元素,然后按指定顺序重新链接;第二种通过直接操作链表反转后半部分,实现更高效的链表重组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…

You must do this in-place without altering the nodes' values.

For example,
Given {1,2,3,4}, reorder it to {1,4,2,3}.

思路(1):喜欢效率较高的盆友直接看思路(2)
  此题要求在不改变节点value值的情况下,写出完整代码,给我的第一感觉就是又是乱七八糟的指针操作(对于指针操作,一般需要缓存当前访问的节点,当前访问节点的next节点等等)。看到这道题,给我的第一直觉就是如果能用栈去缓存,然后一边出栈,一边移动链表指针,这样问题就解决了,于是第一版的思路出来了。

public void reorderList(ListNode head) {
        if(head == null)
            return;
        Stack<ListNode> stack = new Stack<ListNode>();
        ListNode node = head;
        int elementNum = 0;
        //将所有元素入栈
        while(node !=null){
            stack.push(node);
            node = node.next;
            elementNum++;
        }
        ListNode nowPos = head;
        ListNode nextPos = null;
        ListNode tailPos = null;
        for(int i = 0;i<elementNum/2;i++){
            if(tailPos != null)
                tailPos.next = nowPos;
            nextPos = nowPos.next;
            tailPos = stack.peek();
            nowPos.next = stack.pop();
            nowPos= nextPos;
        }

    }

  但这套代码在LeetCode显示Memory Limit Exceeded,也就是说,此种方法内存开销会相当大,那么有没有另外的解决办法呢?
思路(2):
  其实细心的盆友就可以看出来,将所有元素入栈是极大的浪费,因为我们需要反转的就是后半部分,但不是用Stack去缓存链表,而是直接操作链表反转,这样第二种思路就出现了。

        public void reorderList(ListNode head) {  
            if (head == null || head.next == null) return;  

            //把整个链表划分成2个等长的子链表,如果原链表长度为奇数,那么第一个子链表的长度多1  
            ListNode slow = head, fast = head;  
            while (fast.next != null) {  
                fast = fast.next;  
                if (fast.next != null) fast = fast.next;  
                else break;  
                slow = slow.next;  
            }  

            ListNode head1 = head, head2 = slow.next;  
            slow.next = null;  

            //翻转第二个子链表  
            ListNode cur = head2, post = cur.next;  
            cur.next = null;  
            while (post != null) {  
                ListNode tmp = post.next;  
                post.next = cur;  
                cur = post;  
                post = tmp;  
            }  
            head2 = cur;  

            //将两个子链表合并  
            ListNode node1 = head1, node2 = head2;  
            while (node2 != null) {  
                ListNode tmp1 = node1.next;  
                ListNode tmp2 = node2.next;  
                node1.next = node2;  
                node2.next = tmp1;  
                node1 = tmp1;  
                node2 = tmp2;  
            }  
        } 

  LeetCode上显示Runtime: 384 ms,Your runtime beats 97.45% of java coders.性能相当不错了。其实这题还有其它的思路,有兴趣的可以思索一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值