Q16-LeetCode328-奇偶链表

12 阅读2分钟

实现思路

方法1.1

1 重点是需要明白,1次循环内实现 和 2轮循环单独处理的区别

  • 1次循环内:此时虽然p1.next 被改变了,但是没有破坏p2.next的引用关系,所以还能正确移动p2
  • 分开2次循环:在1次循环后,相当于原链表此时已经变成了 原来奇数位置组成的链表, 这时 p2.next的引用关系已被 彻底破坏,所以是不正确的

2 p1.next && p2.next能同时处理 奇数和偶数个数的情况

  • 总数是奇数个:p2.next不会是null, 但是在进入循环执行后,p1会指向最后一个奇数,且p1.next为null && p2指向null;

  • 总数是偶数个:p2.next会指向null,不会进入循环

方法1.2

1 要理解交替移动的指针,其循环终止条件:偶数之后无下一个节点 && 最后一个奇数指向节点不能是null

参考文档

1.1- 方法1.1参考实现

1.2- 方法1.2参考实现

2- 其他一种递归实现

代码实现

1 方法1.1: 迭代- 间隔移动 时间复杂度: O(n) 空间复杂度: O(1)

function oddEvenList(head) {
  if (!head || !head.next) return head;
  let p1Head = head, p2Head = head.next;
  let p1 = head, p2 = head.next;
  // 易错点:需要明白在1轮循环 和 2轮循环的区别
  // 能同时支持奇数和偶数的情况:
  //   - 总数是奇数个:p2.next不会是null
  //     但是在进入循环执行后,p1会指向最后一个奇数,且p1.next为null && p2指向null;
  //   - 总数是偶数个:p2.next会指向null,不会进入循环
  while (p1.next && p2.next) {
    p1.next = p1.next.next;
    p2.next = p2.next.next
    p1 = p1.next
    p2 = p2.next
  }
  p1.next = p2Head;
  return p1Head;
}

2 方法1.2: 迭代- 交替移动 时间复杂度: O(n) 空间复杂度: O(1)

function oddEvenList(head) {
  if (!head || !head.next) return head;
  let p2Head = head.next
  let p1 = head, p2 = head.next;
  // p2不为null 保证了奇数个数 正确终止的情况
  // p2.next不为null 保证了偶数个数时 p1不会错误指向最后1个奇数的 后一位null的情况
  while (p2 && p2.next) {
    p1.next = p2.next
    p1 = p1.next
    p2.next = p1.next
    p2 = p2.next
  }
  p1.next = p2Head;
  return head;
}

3 方法2: 递归实现 时间复杂度: O(n); 空间复杂度(n)

let oddTail = null
function oddEvenList(head: ListNode | null): ListNode | null {
  if (!head || !head.next) return head
  // S1 子问题
	let [, evenHead] = sortOddAndEven(head, head.next)
  // S2 本轮操作:让奇数尾节点指向分类好的偶数头节点
	oddTail.next = evenHead
  // S3 返回分类连接的头节点
	return head
};

// odd-->odd; even-->even; 返回分类好的 [oddHead, evevHead]
function sortOddAndEven(odd, even)  {
	if (!odd.next || !even.next) {
    // 易错点:防止odd后还有一个偶数位置指向
    odd.next = null
    oddTail = odd
		return [odd, even]
	}
	let [newOddHead, newEvenHead] = sortOddAndEven(odd.next.next, even.next.next)
	odd.next = newOddHead
	even.next = newEvenHead
	return [odd, even]
}