以下示例
方法一
看到题目最先想到是多次反转链表,链表不支持下标访问,无法访问到任意位置的元素,我们可以用线性表的方法来存储
在idea测试, ListNode类
public class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
// 添加新的结点
public void add(int newval) {
ListNode newNode = new ListNode(newval);
if(this.next == null)
this.next = newNode;
else
this.next.add(newval);
}
// 打印链表
public void print() {
System.out.print(this.val);
if(this.next != null)
{
System.out.print("-->");
this.next.print();
}
}
}
Test类
public class Test {
public static void main(String[] args) {
ListNode l1 =new ListNode(1);
l1.add(2);
l1.add(3);
l1.add(4);
l1.add(5);
l1.print();
Solution s =new Solution();
s.reorderList(l1);
System.out.println();
l1.print();
}
}
输出:
1-->2-->3-->4-->5
1-->5-->2-->4-->3
package Leetcode143;
import java.util.ArrayList;
import java.util.List;
public class Solution {
public void reorderList(ListNode head) {
if(head==null){ //判断是否为空
return;
}
List<ListNode>list =new ArrayList<ListNode>(); //创建线性表,可以通过下标访问
ListNode node =head;
while (node!=null){
list.add(node); //向list里存储node节点
node=node.next; //同时完成node节点的后移
}
int i=0,j= list.size()-1; //双向取值,此时可以通过下标进行调整
while(i<j){
list.get(i).next=list.get(j); //举例 取了value(1)后,将下标j==4 的节点(value=5)取到,赋值到
// list.get(0).next 里面
i++;
if(i==j){
break;
}
list.get(j).next=list.get(i); //同理,将原节点2(value=2)跟到节点5(value ==5)后面
j--;
}
list.get(i).next = null; //此时i 已经到尾部
}
}
方法二
采用递归的方法 (递归的思路不止一种)
这里的递归采用两头缩进的方式,每次按顺序取头结点,尾结点,然后length-2 再取里层的头结点和尾结点
package Leetcode143;
import java.util.ArrayList;
import java.util.List;
public class Solution {
public void reorderList(ListNode head) {
if (head == null || head.next == null || head.next.next == null) {
return;
}
int len = 0;
ListNode h = head;
while (h != null) {
len++;
h = h.next;
}
reorderListRecursion(head, len);
}
private ListNode reorderListRecursion(ListNode head, int len) {
if (len == 1) { //这两种是为了考虑节点个数奇偶的情况,这种递归出口,是为了返回新的尾结点,头结点只需head.next
ListNode outTail = head.next; //就能获取
head.next = null;
return outTail;
}
if (len == 2) {
ListNode outTail = head.next.next;
head.next.next = null;
return outTail;
}
ListNode tail = reorderListRecursion(head.next, len - 2); //得到里层链表尾结点
ListNode subHead = head.next;// 新的头结点
head.next = tail;
ListNode outTail = tail.next; //新的尾结点
tail.next = subHead;
return outTail;
}
//在不创建线性表的情况下,通过递归改变了关系
}
总结
方法一,较为直接,方法二的递归需要一定的思考,在链表中头结点,和尾结点的更新包含next指向问题,需要想清楚,不然会有一些小错误,这题还有快慢指针的解法,用快慢指针找到链表中点,反转链表,再将链表合并,在之后可能相关的题型里,会对此加以补充。