关于链表反转是招聘笔试中经常考的题,而且经常是让直接写在纸上,感觉在纸上写程序比使用IDE写难好多,主要还是自己不太熟练,所以整理了一下链表的反转的方法。
关于链表反转个人想到了三种方法,使用java实现,后续看到新方法会补充……
链表反转
- 新链表从最后一个节点向前新建,依次拷贝原链表的数据。
- 先将链表中的数据拷贝到一个数组中,从数组最后一个元素依次向前新建链表,这个链表新建的方式是从前向后新建
- 直接使用三个变量来反转原链表
依次来看一下代码
链表结构
class Linked{
int node;
Linked next;
}
1、新链表从最后一个节点向前新建,依次拷贝原链表的数据。
/**
* 方式一
* 思路:新建一个新的链表,新链表从最后一个节点向前新建
* @param head
* @return
*/
public static Linked reverseLinked1(Linked head){
Linked l = null;
Linked linked = head.next;
/**
* 新链表从后向前构建
*/
while(linked!=null){
if(l == null){
// 构建新链表末尾节点
l= new Linked();
l.node = linked.node;
}else{
// 构建当前节点l前一节点temp
Linked temp = new Linked();
temp.next = l;
temp.node = linked.node;
// 更新当前节点为前一节点
l = temp;
}
// 迭代遍历原始链表
linked = linked.next;
}
// 新链表的链表头
Linked h = new Linked();
// 链表头指向第一个节点
h.next = l;
return h;
}
2、借助数组反转
/**
* 方式二
* 思路:首先将链表内容拷贝到数组中,然后以数组反序新建一个链表,新链表从第一个节点向后新建
* @param head
* @return
*/
public static Linked reverseLinked2(Linked head){
// 返回的链表头
Linked new_h = new Linked();
// 获取输入链表的第一个节点
Linked linked = head.next;
// 新链表拷贝到的数组(这里提前定义数组大小如果链表节点数超过这个100就会出错)
int[] a = new int[100];
// 记录链表节点个数
int k=0;
// 拷贝链表数据到数组
while(linked!=null){
a[k] = linked.node;
k++;
linked = linked.next;
}
/*
* 从头开始向后建链表
*/
Linked l = null;
for(int i=k-1;i>=0;i--){
if(l==null){
// 构建第一个节点
l=new Linked();
// 拷贝数据
l.node = a[i];
// 让新链表头指向第一个节点
new_h.next=l;
}else{
// 构建下一个节点
Linked temp = new Linked();
// 拷贝数据
temp.node = a[i];
// 关联两个节点,让当前节点指向下一节点
l.next = temp;
// 更新当前节点
l=temp;
}
}
return new_h;
}
3、使用三个辅助变量反转
/**
* 方式三
* 使用三个变量,分别是前一节点、当前节点、后一节点来反转链表
* @param head
* @return
*/
public static Linked reverseLinked3(Linked head){
Linked current_linked = head.next;
Linked previous_linked = null;
while(current_linked!=null){
// 存储当前点的下一节点
Linked next_linked = current_linked.next;
// 将当前点下一节点更新为前一节点(这一步实现反转)
current_linked.next = previous_linked;
// 前一节点更新为当前点
previous_linked = current_linked;
// 当前点更新为下一点
current_linked = next_linked;
}
// 将链表头指向反转后的链表第一个节点
head.next = previous_linked;
return head;
}