剑指offer(第16题)
与链表相关的问题总是有大量的指针操作,而指针操作的代码总是容易出错的,所以很多笔试,面试都有与链表相关的题目,就是想通过指针操作来考察其编码功底,当然,为了避免出错,在我们写代码之前应该进行全面的分析.
- 在这里直接看图,因为需要反转链表,所以必须在反转之前把下一个节点保存起来,这里定义了三个指针(为什么定义三个,小伙伴可以自己思考一下)
index:正在处理的节点
next:正在处理节点的后一个节点
second:正在处理节点的后两个节点
使第二个节点的指针指向第一个节点,并且第一个节点指针赋为null(只有第一个节点需要).
三个节点依次向后移.
就这样如此循环往复即可.当然这里还需要注意两种情况 - 该链表只有一个节点,那么可以直接返回该节点
- .如果该链表长度为0,也就是头结点的指针也为空,我们的代码也应该能 处理这种情况.
下面附上代码.
/**
* 反转链表,并返回反转链表后的头节点.
* 思路:
* 给三个指针,分别指向正在处理的节点.
* 正在处理节点的后一个节点
* 正在处理节点的后两个节点
* 因为在对指针修改之前,需要保存之前的值.修改了某一个节点后,三个指针依次往后移即可.
*
* 需要考虑两点:
* 1.链表只有一个节点的情况.
* 2.输入头节点为null
*/
public class Question16 {
public static void main(String[] args) {
//这里只是我自己以前实现的链表,直接拿来用,小伙伴可以写一个简单的节点类.
MyLinkedList<Integer> list = new MyLinkedList<>();
//增加节点方法,在第0位,增加存储内容为数字0的节点
list.add(0,0);
list.add(1,1);
list.add(2,2);
list.add(3,3);
list.add(4,4);
MyLinkedList.Node firstNode = invertList(list.getNode(0));
while(firstNode!=null){
System.out.println(firstNode.e);
firstNode = firstNode.nextNode;
}
}
private static MyLinkedList.Node invertList(MyLinkedList.Node first) {
if(first==null)
return null;
//有一个节点的情况
if(first.nextNode==null)
return first;
MyLinkedList.Node index=first; //依次指向链表中的所有节点
MyLinkedList.Node next=first.nextNode; //指向正在处理节点的后一个节点.
MyLinkedList.Node second=next.nextNode; //指向正在处理节点的后两个节点.
//有两个或两个以上的节点,注意这里不能以second作为循环条件,否则就会落下最后一个节点
while(next!=null){
if(index==first) index.nextNode=null;
//后一个节点的指针指向当前节点
next.nextNode=index;
//三个指针依次向后移
index=next;
next=second;
if(second!=null)
second=second.nextNode;
}
return index;
}
}
输出结果,如图:
- 其实这只是其中一种方法,另一种方法是通过递归实现的,也就是直接从最后一个节点开始处理,这时候就不再需要节点来保存了,因为递归其实是用栈实现的,栈这种数据结构帮我们保存了这些信息,如果伙伴想看代码,可以再评论中指出.
- 最后如果对代码中某些地方有疑问,或者感觉有些不妥之处,或者也想看MyLinkList的完整代码,都非常欢迎在评论中指出,谢谢.