网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
方法二:就地反转
头结点插入法的实质是重新创建了一个新的链表,通过遍历待反转链表,将链表每一个节点插入到创建的链表中,然后的到的这个创建的链表就是反转后的链表。而就地反转实质就是在待反转链表基础上修改节点顺序得到反转链表。所以原理还是不同的。
图解:
个人认为就地反转比头结点插入稍微难理解一点。
宏观上来看,要实现节点1和节点2反转,需要将节点1插入节点2和节点3当中,然后将头节点为2的链表插入结果链表头结点后面,然后再后移一个节点做同样的操作。
然而涉及到两个节点的循环赋值,这个操作顺序就比较重要了。
正确的步骤是先将节点2切分出来,再将节点2插入-1和1之间。
实现步骤
- 创建一个带头节点的链表resultList,头结点指向待反转的链表。
- 创建p、pNext两个用于循环操作,分别指向两个待反转节点的位置,初始值如图所示,指向1和2
- 遍历带反转的链表,循环条件是pNext!=null.
3.1 从链表中分割出pNext节点,也就是让p指向pNext->next。
3.2 让pNext指向经过3.1操作之后的resultList.next(1->3->4->5)
3.3 让resultList头结点指向pNext(2->1->3->4->5)
3.4 让pNext指向p的下一个节点
难点在于理解循环中resultList.next指向性的变化,以及p和pNext两个变量的变化,p指向的链表首结点永远是1,只是节点1在resultList链表中位置在发生变化,而pNext是随着p移动的,脑子中间可以有一个摆绳模型,在起始点位置发力,绳子的高点位置会移到绳尾,那个最高点就是p变量位置。
代码实现:
头结点插入:
public static ListNode reverseListByInsert(ListNode listNode){
//定义一个带头节点的
ListNode resultList = new ListNode(-1);
//循环节点
ListNode p = listNode;
while(p!= null){
//保存插入点之后的数据
ListNode tempList = p.next;
p.next = resultList.next;
resultList.next = p;
p = tempList;
}
return resultList.next;
}
就地反转:
public static ListNode reverseListByLocal(ListNode listNode){
ListNode resultList = new ListNode(-1);
resultList.next= listNode;
ListNode p = listNode;
ListNode pNext = p.next;
while (pNext!=null){
p.next = pNext.next;
pNext.next = resultList.next;
resultList.next = pNext;
pNext=p.next;
}
return resultList.next;
}
单链表的操作困扰了很多年,或许还将困扰下去,但是至少有了更加深入的认识。这部分内容确实相对有点难以理解。推荐的学习方法就是先看别人代码,再画图了解代码的每一个过程,再根据画的图独立写代码实现,然后再调试debug,查看变量变化情况,再找类似练习题,多想多练。(就地反转的方法还需要细讲)。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**