算法学习网址:wansuanfa.com (玩算法的拼音)
这题是LeetCode的第92题,难度是中等,一网友在百度一面的面试中遇到这题,结果没做出来,直接挂了。如果因为这题挂了确实有点遗憾,毕竟这题不难,并且很多大厂都喜欢考这题。
我们从下面的评论区可以看出,这题简直是大厂的最爱,快手,字节,百度,小米,美团,猿辅导都考过,就连实习都考这题,尤其是快手和字节,这题都快被他们烤焦了。
从他们的评论中可以看到,多数网友在面试中应该是没做出来。所以如果想进大厂最好把这道题完全掌握,万一哪天去面试的时候考到也能轻松应对,这样就能让你在众多面试者中脱颖而出,鹤立鸡群。
问题描述
来源:LeetCode第92题
难度:中等
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表 。
示例 1:
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
问题分析
这题让把单链表从left到right之间的所有节点反转,反转链表我们都知道,但这题只让反转链表的一部分。一种常见的解决思路就是通过遍历把链表拆成3部分,反转中间的部分,最后在把它们拼接一起。
这里要注意拆成的3部分有可能前面部分或后面部分是空链表,比如示例1中当left等于1的时候,前面部分就是一个空的链表,当right等于5的时候后面部分也是一个空链表。
这种方式比较简单,代码就不在写了,我们来看另外一种解决思路,头插法。
就是把需要反转的节点从前往后不断的往前插入即可完成反转。比如示例1中:[1,2,3,4,5],从2到4反转,刚开始2是不变的,从3开始往前插入。
1,把3插入到前面[1,3,2,4,5]
2,把4插入到前面[1,4,3,2,5]
假如把3插入到前面,我们画个图来看下怎么插入的,这里需要3个指针,cur是当前需要往前插入的节点,pre始终是cur的前一个节点,也是left指向的节点,是不会变的,startPre是开始反转的前一个节点,也是不会变的,这里只有cur指针是一直变动的。
public ListNode reverseBetween(ListNode head, int left, int right) {
// 为了方便处理,先创建一个哑节点,让他指向head。
ListNode dummy = new ListNode(0);
dummy.next = head;
// 记录开始反转节点的前一个节点,也就是left的前一个节点。
ListNode startPre = dummy;
for (int i = 0; i < left - 1; i++)
startPre = startPre.next;
// 记录当前反转节点的前一个节点,这个节点也就是left指向的节点,一直不变。
ListNode pre = startPre.next;
// 记录当前需要反转的节点。
ListNode cur = pre.next;
// 采用头插法,把后面的节点都插入到前面
for (int i = 0; i < right - left; i++) {
pre.next = cur.next;// 让pre指针指向cur的下一个节点
cur.next = startPre.next;// 这两行是把cur节点插入到前面
startPre.next = cur;
cur = pre.next;// 更新cur节点
}
return dummy.next;
}
-------------------------end-------------------------
笔者简介
博哥,真名:王一博,毕业十多年,《算法秘籍》作者,专注于数据结构和算法的讲解,在全球30多个算法网站中累计做题2000多道,在公众号中写算法题解700多题,对算法题有自己独特的解题思路和解题技巧,喜欢的可以给个关注。