「这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战」
再学习链表之后,一定要做题巩固,下面是关于链表比较常见的一些题目,上题目
1. 将两个升序链表合并为⼀个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例: 输⼊:1->2->4, 1->3->4 输出:1->1->2->3->4->4
实现思想:
- 首先确定解题的数据结构:这里使用单链表比较快速
- 假设我们把两个链表分别称作链表a和链表b。从链表头开始比较,链表a和链表b都是有序递增的,所以比较链表a和链表b的第一个元素的较小值就是合并后链表的最小值。合并后链表的第二位就是小节点的next.element,与大节点的element的比较大小,依次递归,直到递归到链表a和链表b均为null
- 确定边界条件:当递归到任意链表为null,直接将next后继指针指向另外的链表即可,不需要再继续递归了
function mergeTwoLists(a, b) {
//代码1
if (a === null) return b;
if (b === null) return a;
//代码2
if (a.element <= b.element) {
a.next = mergeTwoLists(a.next, b)
return b
} else {
b.next = mergeTwoLists(b.next, a)
return b
}
}
代码解读: 代码1:如果链表一方不存在的情况下,直接返回另一个链表即可
2. 判断一个单链表是否有环
题目描述:给定一个链表,判断链表中是否有环。 为了表示给定链表中的环,我们使⽤整数pos来表示链表尾连接到链表中的位置(索引从0开始)。如> 果pos是-1 ,则在该链表中没有环。 输⼊:head = [3,2,0,-4],pos = 1 输出:true 解释:链表中有⼀个环,其尾部连接到第⼆个节点。
这里有两种解法:
1. 节点标记法
实现思想:给每一个已遍历过的节点加上一个标志,遍历链表,当出现下一个节点已被标记过的时候,说明链表中有环
function hasCircle(head) {
while (head) {
if (head.flag) return true;
head.flag = true;
head = head.next;
}
return false
}
2. 快慢指针(双指针)
这是实现这个问题最常用也是面试最想问的一个答案
实现思想:设置快慢两个指针,遍历单链表,快指针一次走两步,慢指针一次走一步,如果是单链表中存在和环,则快慢指针终会指向同一个节点,否则直到快指针指向null,快慢指针都不可能相遇.
function hasCircle2(head){
//代码1
if(!head || !head.next){
return false
}
// 代码2
let fast = head.next.next;
let slow = head.next;
// 代码3
while(fast != slow){
if(!fast || !fast.next) return false;
fast = fast.next.next;
slow = slow.next;
}
return true
}
代码解读: 代码1:判断链表是否存在,并且是否有值 代码2:设置快指针fast是链表的第三个元素,慢指针是链表的第二个元素 代码3:循环判断快慢指针是否相等,判断链表中是否有