算法为编程语言的基础
技术面试中,面试官一般会先就你所应聘的岗位进行相关知识的考察,也叫基础知识和业务逻辑面试。只要你回答的不是特别特别差,面试官通常会说:“咱们写个代码吧”,这个时候就开始了算法面试。也就是说,一轮技术面试=基础知识和业务逻辑面试+算法面试。
一次字节跳动面试的感慨
前段时间,我曾面试字节跳动,面试官的一道算法题算是把我给难住了,给大家还原当时的面试场景如下:
面试官:给定单链表的头结点 head,实现一个调整链表的函数,从链表尾部开始,以 K 个结点为一组进行逆序翻转,头部剩余结点不足一组时,不需要翻转。(不能使用队列或者栈作为辅助)
但是这个算法题困扰了我很久,一直苦苦得不出答案。最后还是在面试官的提醒下才知晓正确的答案。
正确答案如下:
我们先定义一个 reverseKGroupPlus() 方法
public ListNode reverseKGroupPlus(ListNode head, int k) {
if (head == null || k <= 1) return head;
// 计算原始链表长度
int length = linkedLength(head);
if (length < k)
return head;
// 计算 offset
int offsetIndex = length % k;
// 原始链表正好可以由 K 分位 N 组,可直接处理
if (offsetIndex == 0) {
return reverseKGroup(head, k);
}
// 定义并找到 prev 和 offset
ListNode prev = head, offset = head;
while (offsetIndex > 0) {
prev = offset;
offset = offset.next;
offsetIndex--;
}
// 将 offset 结点子链表进行翻转,再拼接回主链表
prev.next = reverseKGroup(offset, k);
return head;
}
注意当链表长度正好可以用 K 分位 N 组时,我们直接处理,否者才需要后续复杂的逻辑。
代码的注释足够清晰了,在脑子里过一遍代码的执行流程应该能明白,为了帮助大家理解,我又画了个示意图。
假设以 head 为头结点的链表长度是 10,K 为 4,那么计算下来 offset Index 就是 2。
找到 prev 和 offset 结点后,就可以将以 offset 结点为头结点的子链表,进行 K 个一组翻转链表的操作了。
此时,head 结点位起始的链表,就是我们计算后的结果。
面试官当时跟我交谈3个小时,说算法其实不算难,而且算法是程序编程的基础之一是一定要掌握的,给我推荐了一本算法笔记。笔记领取方式:关注、转发后私信小编【算法】即可领取
笔记一共分为7个小节,详细叙述了算法的厉害之处。
- 排序和查找算法
- 查找算法
- 二叉树
- 队列和栈
- 字符串
- 数组
- 其它算法
排序算法
- 希尔排序
- 原地归并的抽象方法
- 自顶向下的归并排序
- 自底向上的归并排序
- API
- 堆的算法
- 堆排序
查找算法
- 无序链表中的顺序查找
- 有序数组中的二分查找
- 二分查找的分析
- 二叉查找树的基本实现
- 平衡查找树的基本实现
- 红黑树的性质
- 散列函数
二叉树
- 二叉树中序遍历
- 二叉树的序列化和反序列化
- 子树
- 最近公共祖先
- 二叉树的层次遍历
- 将二叉树拆成链表
- 在二叉查找树中插入节点
队列和栈
- 带最小值操作的栈
- 用栈实现队列
- 有效的括号序列
- 简化路径
字符串
- 罗马数字转整数
- 回文数
- 乱序字符串
- 有效回文串
- 翻转字符串
- 最长无重复字符的子串
- 字符串压缩
- 比较字符串
- 编辑距离1I
数组
其它算法
文末笔记领取方式
笔记领取方式:点赞+关注,加助理VX:mxx2020666,即可免费领取