加入收藏 | 设为首页 |

初七-记一道字节跳动的算法面试题

海外新闻 时间: 浏览:367 次

戳蓝字“CSDN云核算重视咱们哦!

来历大众号:苦逼的码农作者:帅地

前几天有个朋友去面试字节跳动,面试官问了他一道链表相关的算法题,不过他一时之间没做出来,就来问了我一下,感觉这道题还不错,拿来讲一讲。

标题

这其实是一道变形的链表回转题,大致描绘如下

给定一个单链表的头节点 head,完成一个调整单链表的函数,使得每K个节点之间为一组进行逆序,而且从链表的尾部开端组起,头部剩下节点数量不行一组的不需求逆序。(不能运用行列或许栈作为辅佐)

例如:链表:1->2->3->4->5->6->7->8->, K = 3。那么 6->7->8,3->4->5,1->2各位一组。调整后:1->2->5->4->3->8-初七-记一道字节跳动的算法面试题>7->6->。初七-记一道字节跳动的算法面试题其间 1,2不调整,由于不行一组。

回答

这道题的难点在于,是从链表的尾部开端组起的,而不是从链表的头部,假如是头部的话,那咱们仍是比较简单做的,由于你能够遍历链表,每遍历 k 个就拆分为一组来逆序。可是从尾部二线城市的话就不相同了,由于是单链表,不能往后遍历组起。不过这道题肯定是用递归比较好做,对递归不大懂的主张看我之前写的一篇文章为什么你学不会递归?离别递归,谈谈我的一些经历,这篇文章写了关于递归的一些套路。

先做一道类似的回转题

在做这道题之前,咱们不仿先来看看假如从头部开端组起的话,应该怎样做呢?例如:链表:1->2->3->4->5->6->7->8->, K = 3。调整后:3->2->1->6->5->4->7->8->。其间 7,8不调整,由于不行一组。

关于这道题,假如你不知道怎样逆序一个单链表,那么能够看一下我之前写的怎么高雅着回转单链表

这道题咱们能够用递归来完成,假定办法reverseKNode的功用是将单链表的每K个节点之间逆序(从头部开端组起的哦);reverse办法的功用是将一个单链表逆序。

那么关于下面的这个单链表,其间 K = 3。

咱们把前K个节点与后边的节点切割出来:

temp指向的剩下的链表,能够说是原问题的一个子问题。

咱们能够调用reverseKNode办法将temp指向的链表每K个节点之间进行逆序。

再调用reverse办法把head指向的那3个节点进行逆序,成果如下:

再次声明,假如对这个递归看不大懂的,主张看下我那篇递归的文章

接着,咱们只需求把这两部分给连接起来就能够了。最终的成果如下:

代码如下:

 //k个为一组逆序
public ListNode reverseKGroup(ListNode head, int k) {
ListNode temp = head;
for (int i = 1; i < k && temp != ; i++) {
temp = temp.next;
}
//判别节点的数量是否能够凑成一组
if(temp == )
return head;

ListNode t2 = temp.next;
temp.next = ;
//把当时的组进行逆序
ListNode newHead = reverseList(head);
//把之后的节点进行分组逆序
ListNode newTemp = reverseKGroup(t2, k);
// 把两部分连接起来
head.next = newTemp;

return newHead;
}

//逆序单链表
private static ListNode reverseList(ListNode head) {
if(head == || head.next == )
return head;
ListNode result = reverseList(head.next);
head.next初七-记一道字节跳动的算法面试题.next = head;
head.next = ;
return result;
}

回到本题

这两道题能够说是及其类似的了,仅仅一道从头部开端组起,这道从头部开端组起的,也是 leetcode 的第 25 题。而面试的时分,经常会进行变形,例如这道字节跳动的题,它变成从尾部开端组起,或许你一时之间就不知道该怎样弄了。当然,或许有人一会儿就反响出来,把他秒杀了。

其实这道题很好做滴,你只需求先把单链表进行一次逆序,逆序之后就能转化为从头部开端组起了,然后依照我上面的解法,初七-记一道字节跳动的算法面试题处理完之后,把成果再次逆序即搞定。两次逆序相当于没逆序。

例如关于链表(其间 K = 3)

咱们把它从尾部开端组起,每 K 个节点为一组进行逆序。

过程如下

1、先进行逆序

逆序之后就能够把问题转化为从头部开端组起,每 K 个节点为一组进行逆序。

2、处理后的成果如下

3、接着在把成果逆序一次,成果如下

代码如下

public ListNode solve(ListNode head, int k) {
// 调用逆序函数
head = reverse(head);
// 调用每 k 个为一组的逆序函数(从头部开端组起)
head = reverseKGroup(head, k);
// 在逆序一次
head = reverse(head);
return head;

}

类似于这种需求先进行逆序的还要两个链表相加,这道题字节跳动的笔试题也有出过,如下图的第二题

这道题就需求先把两个链表逆序,再节点间相加,最终在兼并了。

总结

关于链表的算法题,在面试的时分听说是挺常考的,我们能够多留意留意,遇到不错的链表算法题,也欢迎扔给我勒。