LeetCode 143 重排链表

题目描述:

给定一个单链表 L 的头节点 head ,单链表 L 表示为:

L_{0}\rightarrow L_{1}\rightarrow \cdot \cdot \cdot \rightarrow L_{n - 1}\rightarrow L_{n}

请将其重新排列后变为:

L_{0}\rightarrow L_{n}\rightarrow L_{1} \rightarrow L_{n - 1}\rightarrow L_{2} \rightarrow L_{n - 2}\rightarrow \cdot \cdot \cdot

不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。


示例:

输入:head = [1, 2, 3, 4]

输出:[1, 4, 2, 3]

输入:head = [1, 2, 3, 4, 5]

输出:[1, 5, 2, 4, 3]


个人解法(双端队列):

首先进行遍历将链表节点依次入队,然后对该队列交替进行出队头元素,出队尾元素,直到队列为空,将每次取出的节点连接到结果链表上,最后将结果链表末尾节点的 next 置空,防止链表中出现环

public void reorderList(ListNode head) {
	ListNode cur = head;
	Deque<ListNode> nodeDeque = new LinkedList<>();
	while (cur != null) {
		nodeDeque.add(cur);
		cur = cur.next;
	}
	ListNode temp;
	cur = new ListNode(0, head);
	int i = 0;
	while (!nodeDeque.isEmpty()) {
		if (i % 2 == 0) {
			temp = nodeDeque.removeFirst();
		} else {
			temp = nodeDeque.removeLast();
		}
		cur.next = temp;
		cur = cur.next;
		i++;
	}
	cur.next = null;
}

官方解法1(线性表):

首先进行遍历将链表节点依次存入 ArrayList ,然后利用线性表可以随机访问的特性,用两个变量 i 、j 控制顺序访问即可

public void reorderList1(ListNode head) {
	List<ListNode> list = new ArrayList<ListNode>();
	ListNode node = head;
	while (node != null) {
		list.add(node);
		node = node.next;
	}
	int i = 0, j = list.size() - 1;
	while (i < j) {
		list.get(i).next = list.get(j);
		i++;
		if (i == j) {
			break;
		}
		list.get(j).next = list.get(i);
		j--;
	}
	list.get(i).next = null;
}

官方解法2(寻找链表中点 + 链表逆序 + 合并链表):

目标链表为将原链表的左半端和反转后的右半端间隔合并后的结果

快慢指针法寻找中间节点,迭代法实现链表逆序,最后将两个链表间隔合并即可

public void reorderList2(ListNode head) {
	if (head == null) {
		return;
	}
	ListNode mid = middleNode(head);
	ListNode l1 = head;
	ListNode l2 = mid.next;
	mid.next = null;
	l2 = reverseList(l2);
	mergeList(l1, l2);
}

public ListNode middleNode(ListNode head) {
	ListNode slow = head;
	ListNode fast = head;
	while (fast.next != null && fast.next.next != null) {
		slow = slow.next;
		fast = fast.next.next;
	}
	return slow;
}

public ListNode reverseList(ListNode head) {
	ListNode prev = null;
	ListNode curr = head;
	while (curr != null) {
		ListNode nextTemp = curr.next;
		curr.next = prev;
		prev = curr;
		curr = nextTemp;
	}
	return prev;
}

public void mergeList(ListNode l1, ListNode l2) {
	ListNode l1_tmp;
	ListNode l2_tmp;
	while (l1 != null && l2 != null) {
		l1_tmp = l1.next;
		l2_tmp = l2.next;
		l1.next = l2;
		l1 = l1_tmp;
		l2.next = l1;
		l2 = l2_tmp;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_25274377/article/details/120284557