前端面试中,算法题也是特别常见的类型,我们将在未来新增一个LeetCode的专栏,给大家讲解一些常见算法题的解题思路。
刷题刷题,从“刷”字就能看出其中的机械性和应试性,但这就是几乎所有互联网公司面试中的一环。
尽管面试者可能也对这种考察方式不是很满意,可在没有更好的方式之前,这个现状会一直保持下去。我们改变不了这个现状,那就适应它吧。
来说说 Leetcode 试题的几个特点,可能也适用于大部分面试题:
Corner Case
都要考虑到,不然在 Leetcode 上提交时就会被打回,面试时可能也会被质疑。废话不多说,今天先给大家带来一道比较基础的题目 —— 回文链表。
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
在解题之前,我们首先需要理解题目的含义。首先需要理解什么是回文链表。回文一词最初出现在文学作品中,下面是维基百科给出的回文的定义。
回文,亦称回环,是正读反读都能读通的句子,亦有将文字排列成圆圈者,是一種修辭方式和文字游戏。
上面定义可能不太容易理解,简单的可以理解为正读和反读都一样的句子。为了便于理解下面给出几个简单例子。
上海自来水来自海上
黄山落叶松叶落山黄
回文链表的概念与此类似,也就是正向和反向遍历,序列一样的链表。
利用链表的后续遍历,使用函数调用栈作为后序遍历栈,来判断是否回文
var isPalindrome = function(head) {
let left = head;
function traverse(right) {
if (right == null) return true;
let res = traverse(right.next);
res = res && (right.val === left.val);
left = left.next;
return res;
}
return traverse(head);
};
通过快、慢指针找链表中点,然后反转链表,比较两个链表两侧是否相等,来判断是否是回文链表
var isPalindrome = function(head) {
// 反转 slower 链表
let right = reverse(findCenter(head));
let left = head;
// 开始比较
while (right != null) {
if (left.val !== right.val) {
return false;
}
left = left.next;
right = right.next;
}
return true;
}
function findCenter(head) {
let slower = head, faster = head;
while (faster && faster.next != null) {
slower = slower.next;
faster = faster.next.next;
}
// 如果 faster 不等于 null,说明是奇数个,slower 再移动一格
if (faster != null) {
slower = slower.next;
}
return slower;
}
function reverse(head) {
let prev = null, cur = head, nxt = head;
while (cur != null) {
nxt = cur.next;
cur.next = prev;
prev = cur;
cur = nxt;
}
return prev;
}