Reorder List(LeetCode)

题目:

Given a singly linked list LL0L1→…→Ln-1Ln,
reorder it to: L0LnL1Ln-1L2Ln-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}.

题目分析:题干给出了一个链表,需要重新排列顺序。要求,将倒数第一个元素插到第一个元素后面,倒数第二个元素插入到第二个元素后面。。。。。。以此类推。另外,题干要求原地算法(in-place),即需要通过移动原来链表中的节点而不能另创新的链表来完成任务。


思路:

  1. 将链表分为两个部分,前一部分是待插入的链表前部分,后一部分是等待被插入的链表后部分
    • 遍历链表,统计元素个数n,如果个数小于3,则无需调整,直接调用return结束
    • 前半部分长度应该为[n/2]+1,其余为后半部分(长度为[n/2]或者[n/2]-1)
      • 这样分,无论n为奇数还是偶数,全部需要插入的元素即是后部分的全部元素
      • nextHead标记待插入地方的前一个元素,即被插入的元素要插到nextHead.next
      • pos标记等待被插入的元素,pre记录pos的前一个元素,即pre.next==pos
  2. 从后往前,递归地找到正确的被插入元素,插入,并且返回下一个正确的nextHead
    • 先递归地调用nextHead = doInsert (nextHead, pre.next, pos.next)
    • 即待插入的地方nextHead不变,(pre.next和pos.next)每次向后查找正确的被插入元素及其前一个元素
    • 正确的被插入元素即是每次被插入列表的最右端元素
    • 返回一个新的nextHead,即是上一层递归中,pre和pos对应的应该被插入的地方


注意点:

  • 之前写了一个类似思想的算法,但没有用递归。而是,每一次都遍历链表,找到正确的pre和pos。
    • LeetCode上没有通过,TimeLimitedExceed错误。原因是,每次都遍历链表找被插入元素太费时间
    • 利用递归,上一层递归自动记下了被插入元素的pre和pos,只需要每次返回正确的待插入地方nextHead即可




代码:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public void reorderList(ListNode head) {
        ListNode tag = head;
        ListNode pre, pos;
        int len=0;
        while (tag != null){
            len++;
            tag = tag.next;
        }
        if (len <= 2){
            return;
        }
        pre = head;
        for (int i=1; i <= len/2; i++){
            pre = pre.next;
        }
        pos = pre.next;
        ListNode nextHead = head;
        doInsert(nextHead, pre, pos);
        
    }
    
    static ListNode doInsert(ListNode nextHead, ListNode pre, ListNode pos){
        if (pos.next == null){
            pre.next = null;
            pos.next = nextHead.next;
            nextHead.next = pos;
            nextHead = pos.next;
            return nextHead;
        }
        nextHead = doInsert(nextHead,pre.next,pos.next);
        pre.next = null;
        pos.next = nextHead.next;
        nextHead.next = pos;
        nextHead = pos.next;
        return nextHead;
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值