这是我做的两种方法的性能对比
1.第一种方式
将链表list1压入栈,再创建一个链表list2,栈中结点依次弹出添加到list2中。
//第一种解法
public ListNode reverseList(ListNode head) {
Stack<ListNode> stack=new Stack<>();
if(p==null)
return head;
ListNode p=head;
stack.push(p);
while(p.next!=null){ //将链表节点依次入栈
stack.push(p.next);
p=p.next;
}
ListNode list1=stack.pop();//先弹出最后一个节点
ListNode p1=list1;
while(!stack.isEmpty()){ //stack不为空就继续弹出
p1.next=stack.pop();
p1=p1.next; //让新链表的最后一个节点指向弹出的节点
p1.next=null; //将弹出节点指向空
}
return list1;
}
这种解决方式创建了栈和新的链表,占用空间大,而且入栈出栈过程遍历了两次(链表的遍历效率很低,要访问所有节点),复杂度比较高。
2.第二种方式
一次遍历,使用三个指针,将指针方向与原来的指针方向相反即可。
我的表达能力不是很好,描述可能不清除,思路如图所示。
pre 前指针
cur 当前指针
tmp 临时指针
1.待反转的链表
2.申请三个指针,cur,tmp,pre。
// head是第一个节点,也可以说是链表,因为通过第一个节点的指针域可以找到后面的所有节点
// ListNode cur=head;
// ListNode pre=null;
// ListNode tmp=null;
// tmp=cur;
3.第一次操作,先将第一个节点的指针指向null
第一步:先将当前指针cur指向下一个节点。
cur=cur.next;
第二步:将第一个节点指向pre,
由于tmp=cur ,cur=head ,所以tmp就是第一个节点
由于pre=null,所以tmp.next=pre;就是将第一个节点的指针指向null
tmp.next=pre;
第三步:将pre后移一个位置
pre=tmp;
第四步:将tmp后移一个位置
tmp=cur;
4.继续执行3中的第二步,第三步,第四步直到最后一个节点为止
public ListNode reverseList(ListNode head) {
if(head==null)
return head;
ListNode cur=head;
ListNode pre=null;
ListNode tmp=null;
while(cur!=null){
tmp=cur;
cur=cur.next;
tmp.next=pre;
pre=tmp;
}
return pre;
}