- 将一个单向链表反转,最终输出反转后的链表的头节点
废话少说,直接上代码:
单向链表模型,如下
public class ListNode {
public ListNode next;
public int val;
public ListNode(int val){
this.val = val;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
ListNode node = this;
while (node !=null){
sb.append(node.val);
node = node.next;
if (null != node) sb.append(",");
}
sb.append("]");
return sb.toString();
}
}
方法一:遍历元素,依此反转位置
private static ListNode reverseNode1(ListNode root){
ListNode currNode = root.next;//将第二个node作为遍历开始的元素
ListNode reverseNode = root;//将第一个node作为反转的开头
root.next = null;
while (currNode != null){
ListNode temp = currNode.next;//后面没有反转的node放在temp保存
//将之前反转的node放在当前node后面,构建新的反转序列,这是反转的关键操作
currNode.next = reverseNode;
reverseNode = currNode ;//这是反转后node的更新
currNode = temp;//将后面未反转的node保存到temp
}
return reverseNode;
}
方法二:新建链表,依此将原有元素插入到头部
private static ListNode reverseNode2(ListNode node) {
ListNode curNode = node.next;//将第二个元素作为遍历元素的开始
ListNode reverseNode = new ListNode(node.val);//将第一个元素作为反转序列的开头,注意是仅仅copy单个元素
while (curNode != null){
int val = curNode.val;
ListNode curUnit = new ListNode(val);//将当前的元素做单个copy
curUnit.next = reverseNode;//将之前反转好的序列放在当前元素的后面,反转的关键步骤
reverseNode = curUnit;//更新反转后的序列
curNode = curNode.next;//更新当前元素为下一个
}
return reverseNode;
}
测试
public static void main(String[] arg0){
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
//以下测试二选其一,否则互相影响
System.out.println("result 1 = "+reverseNode1(node1).toString());
//System.out.println("result 2 = "+reverseNode2(node1).toString());
}
结果:两个运行结果一致,均为反转后的序列
result 1 = [5,4,3,2,1]
总结
- 方法一与方法二的时间复杂度均为n-1 (假设链表长度为n)
- 方法一的空间复杂度为1,那么方法二的空间复杂度就是2;double了,因为方法二将整个链表完整的复制了一遍