算法思想一:数组
解题思路:
因为链表不支持下标访问,所以我们无法随机访问链表中任意位置的元素。
因此比较容易想到的一个方法是,我们利用线性表存储该链表,然后利用线性表可以下标访问的特点,直接按顺序访问指定元素,重建该链表即可。
因此比较容易想到的一个方法是,我们利用线性表存储该链表,然后利用线性表可以下标访问的特点,直接按顺序访问指定元素,重建该链表即可。
算法步骤:
1、初始化空数组res,遍历链表将链表结点存储到数组中
2、设置双指针i,j
按照题目,res[i].next = res[j],指针 i 加1
再拼接 res[j] 结点, res[j].next = res[i], 指针 j 减1
循环到 i >= j 跳出循环
代码展示:
Python版本
# class ListNode: # def __init__(self, x): # self.val = x # self.next = None # # # @param head ListNode类 # @return void # class Solution: def reorderList(self , head ): # write code here if not head: return # 初始化数组 res = [] node = head while node: res.append(node) node = node.next # 进行链表结点交换 i, j = 0, len(res) - 1 while i < j: res[i].next = res[j] i += 1 if i == j: break res[j].next = res[i] j -= 1 # 指明最后 res[i].next = None
复杂度分析:
时间复杂度O(N):N是链表的结点数量,遍历链表、数组构建新链表
空间复杂度O(N):使用额外的数组空间
算法思想二:寻找链表中点 + 链表逆序 + 合并链表
解题思路:
1、找中点的话,可以使用快慢指针。快指针一次走两步,慢指针一次走一步,当快指针走到终点的话,慢指针会刚好到中点。如果节点个数是偶数的话,slow 走到的是左端点,利用这一点,我们可以把奇数和偶数的情况合并,不需要分开考虑。
2、链表逆序的话,参考 https://blog.nowcoder.net/n/d259b250747b4085bc7975f102d248c4
3、合并链表,两个指针分别向后移动就可以。
2、链表逆序的话,参考 https://blog.nowcoder.net/n/d259b250747b4085bc7975f102d248c4
3、合并链表,两个指针分别向后移动就可以。
图解:
链表:{1,2,3,4,5,6}
步骤 | 操作 | 链表 |
1 | 寻找链表中点,将链表分为两半 | {1,2,3} {4,5,6} |
2 | 将后半链表反转 | {1,2,3} {6,5,4} |
3 | 合并两个链表 | {1,6,2,5,3,4} |
代码展示:
JAVA版本
public class Solution { public void reorderList(ListNode head) { if (head == null || head.next == null || head.next.next == null) { return; } //找中点,链表分成两个 ListNode slow = head; ListNode fast = head; while (fast.next != null && fast.next.next != null) { slow = slow.next; fast = fast.next.next; } ListNode newHead = slow.next; slow.next = null; //第二个链表倒置,反转后半部分链表 newHead = reverseList(newHead); //链表节点依次连接 while (newHead != null) { ListNode temp = newHead.next; newHead.next = head.next; head.next = newHead; head = newHead.next; newHead = temp; } } private ListNode reverseList(ListNode head) { if (head == null) { return null; } ListNode tail = head; head = head.next; tail.next = null; while (head != null) { ListNode temp = head.next; head.next = tail; tail = head; head = temp; } return tail; } }
复杂度分析:
时间复杂度O(N):N是链表的结点数量,遍历链表、重组链表
空间复杂度O(1):使用常数级空间指针