文章简要概述
-
本篇主要是复习链表相关的内容,部分算法题之前可能写过,这里进行回顾,进一步加深印象。
刷题不是目的,目的是理解与掌握。 -
本文一共有4道题,主要介绍leetcode中
面试题 02.02. 返回倒数第 k 个节点、剑指 Offer 22. 链表中倒数第k个节点、剑指 Offer 35. 复杂链表的复制和面试题 02.03. 删除中间节点的解题思路。
与链表相关算法
面试题 02.02. 返回倒数第 k 个节点
面试题 02.02. 返回倒数第 k 个节点 -- leetcode
题目大意:
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。
注意: 本题相对原题稍作改动
示例
输入: 1->2->3->4->5 和 k = 2
输出: 4
解题思路:
- 这道题和之前我们之前做的一道链表题基本一致
- 解题方法可以用链表长度 - k + 1,得到移动的步数,然后正着从链表头部移动到对应位置
- 本题采用链表解题的常用方式快慢指针,让快指针与慢指针之间间隔k,然后同时移动快慢指针,当快指针到达链表尾部时,慢指针所在位置就是倒数第k个节点。
- 本题解题方法还有很多,递归和栈也都能解决,感兴趣可以去leetcode上寻找其他解题技巧。
代码:
/**
* @param {ListNode} head
* @param {number} k
* @return {number}
*/
function kthToLast (head, k) {
let first = head;
let second = head;
while(k > 0) {
first = first.next;
k--;
}
while(first) {
first = first.next;
second = second.next;
}
return second.val;
};
剑指 Offer 22. 链表中倒数第k个节点
剑指 Offer 22. 链表中倒数第k个节点 -- leetcode
题目大意:
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
解题思路:
- 本题与上一题的解题思路很像,都属于找第k个节点的位置
- 上面的说方法基本都可以实现,这里用链表长度 - k 去得到答案
代码:
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
function getKthFromEnd(head, k) {
let first = head;
let l = 0
while(first) {
first = first.next;
l++;
}
let i = 0;
while(i < l-k) {
head = head.next;
i++;
}
return head;
};
剑指 Offer 35. 复杂链表的复制
剑指 Offer 35. 复杂链表的复制 -- leetcode
题目大意:
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
示例:
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
解题思路:
- 本题和之前写的链表三中的
复制带随机指针的链表的题目是一样的,具体解题思路可以看前面的文章。这里是加强练习,不做具体解析
代码:
/**
* @param {Node} head
* @return {Node}
*/
function copyRandomList (head) {
if (!head) return head;
let node = head;
while(node) {
const copyNode = new Node(node.val, node.next, null);
node.next = copyNode;
node = copyNode.next;
}
node = head;
while(node) {
const copyNode = node.next;
copyNode.random = node.random !== null ? node.random.next : null;
node = copyNode.next;
}
const res = head.next;
node = head;
while(node) {
const copyNode = node.next;
node.next = node.next.next;
copyNode.next = copyNode.next !== null ? copyNode.next.next : null;
node = node.next;
}
return res;
};
面试题 02.03. 删除中间节点
题目大意:
若链表中的某个节点,既不是链表头节点,也不是链表尾节点,则称其为该链表的「中间节点」。
假定已知链表的某一个中间节点,请实现一种算法,将该节点从链表中删除。
例如,传入节点 c(位于单向链表 a->b->c->d->e->f 中),将其删除后,剩余链表为 a->b->d->e->f
示例:
输入: 节点 5 (位于单向链表 4->5->1->9 中)
输出: 不返回任何数据,从链表中删除传入的节点 5,使链表变为 4->1->9
解题思路:
- 本题的代码超乎想象的短。
- 题意解释一下:一个给定的链表,然后传进来链表中某一个节点,然后删除传进来的节点,原链表其他不变。
- 解题方法,将传进来的节点内容替换成下一个节点的内容,然后
next指针指向下一位的下一位节点,等于删除自身节点了。感觉这个操作还是比较骚的。
代码:
/**
* @param {ListNode} node
* @return {void} Do not return anything, modify node in-place instead.
*/
var deleteNode = function(node) {
node.val = node.next.val;
node.next = node.next.next;
};
结束语
数据结构与算法相关的练习题会持续输出,一起来学习,持续关注。当前是链表复习部分。后期还会有其他类型的数据结构,题目来源于leetcode。往期文章:
数据结构与算法-栈一 数据结构与算法-栈二 数据结构与算法-队列一 数据结构与算法-队列二
数据结构与算法-链表一 数据结构与算法-链表二 数据结构与算法-链表三
有兴趣的可以一起来刷题,感谢点赞👍 , 关注!