高频题——排序奇升偶降链表

1,031 阅读1分钟

来看一下几篇面经的原文叙述

  • 链表,奇数位置按序增长,偶数位置按序递减,如何能实现链表从小到大?(2020.10 字节跳动-后端)[2]
  • 奇偶生序倒序链表的重新排序组合,例如:18365472(2020.08 字节跳动-后端)[3]
  • 1->4->3->2->5 给定一个链表奇数部分递增,偶数部分递减,要求在O(n)时间复杂度内将链表变成递增,5分钟左右(2020.07 字节跳动-测试开发)[4]
  • 奇数位升序偶数位降序的链表要求时间O(n)空间O(1)的排序?(2020.07 字节跳动-后端)[5]

image.png

image.png

思路很清晰,实现起来其实还是有些难度的,因为这里的每一步其实都可以单独抽出来作为一道题。第2步和第3步分别对应的力扣206. 反转链表和21. 合并两个有序链表,而第1步的解法与328. 奇偶链表差不多。如果搞懂这3道leetcode,那么本篇文章的这道题肯定不在话下了。

public ListNode Solution(ListNode head){
    List<ListNode> list = splitOddEvenList(head);
    ListNode oddHead = list.get(0);
    ListNode evenHead = list.get(1);
    evenHead = reverEvenList(evenHead);
    return mergeOddEvenList(oddHead, evenHead);
}

//奇偶链表拆分
public List<ListNode> splitOddEvenList(ListNode oddhead){
    ListNode evenHead = oddhead.next;
    ListNode curEven = evenHead;
    ListNode curOdd = oddhead;
    while(curOdd!=null && curOdd.next!=null){
        curOdd.next = curOdd.next.next;
        curOdd = curOdd.next;
        if(curOdd==null) break;
        curEven.next = curOdd.next;
        curEven = curEven.next;
    }
    return new LinkedList<ListNode>(Arrays.asList(oddhead,evenHead));
}

//反转链表
public ListNode reverEvenList(ListNode node){
    if(node==null || node.next==null) return node;
    ListNode newHead = reverEvenList(node.next);
    node.next.next = node;
    node.next = null;
    return newHead;
}

// 合并链表
public ListNode mergeOddEvenList(ListNode oddHead,ListNode evenHead){
    if(oddHead==null) return evenHead;
    if(evenHead==null) return oddHead;
    if(oddHead.val<=evenHead.val){
        oddHead.next = mergeOddEvenList(oddHead.next,evenHead);
        return oddHead;
    }else{
        evenHead.next = mergeOddEvenList(oddHead,evenHead.next);
        return evenHead;
    }
}