【JavaScript算法】-链表合辑05:反转链表II、环形链表、环形链表II

一、92 反转链表II

问题描述

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
在这里插入图片描述

解题思路

这个题和206反转列表那道题是类似的,只是这个题目限定了链表反转的范围而已,所以需要注意将反转后的链表拼接回原链表中。

1、虚拟节点+头插法

a、设置虚拟节点dmy指向原链表头节点,找到left前一个节点pre;
b、初始化cur指针指向left节点,使用头插法反转链表,令nex=cur.next,cur.next=pre.next,pre.next=cur;直到cur走到right指向的节点,反转结束;
c、因为right后面可能还有节点,所以需要令原left节点指向cur.next,使链表连接完整;
d、返回dmy.next。
具体代码如下:

/**
 * @param {ListNode} head
 * @param {number} left
 * @param {number} right
 * @return {ListNode}
 */
var reverseBetween = function(head, left, right) {
    if(head==null||head.next==null||left==right) return head;
    let dmy=new ListNode(0,head);
    let pre=dmy;
    let leftnode=head;
    let i=left;
    while(--i){ //找到left指向的节点
        pre=pre.next;
        leftnode=leftnode.next;
    }
    let cur=leftnode;
    for(;left<=right;left++){ //链表反转
        let nex=cur.next;
        cur.next=pre.next;
        pre.next=cur;
        cur=nex;
    }
    //连接right后半部分,使链表成为一个整体
    leftnode.next=cur;
    return dmy.next;
};
2、迭代法

a、设置虚拟节点dmy方便之后返回结果;
b、初始化pre、cur、next节点,left指向的节点和left后一个节点,left后两个节点;
c、反转链表:cur.next=pre,pre、cur、nex后移,直到cur移动到right指向的节点,反转结束;
d、这里为了将链表连接为一个整体,还需要额外记住left指向节点和其前一个节点;
e、返回dmy.next。
具体代码如下:

var reverseBetween = function(head, left, right) {
    if(head==null||head.next==null||left==right) return head;
    let dmy=new ListNode(0,head);
    let pre1=dmy;
    let leftnode=head;
    let i=left;
    while(--i){
        pre1=pre1.next;
        leftnode=leftnode.next;
    }
    let pre=leftnode;
    let cur=leftnode.next;
    for(;left<right;left++){
        let nex=cur.next;
        cur.next=pre;
        pre=cur;
        cur=nex;
    }
    pre1.next=pre;
    leftnode.next=cur;
    return dmy.next;
};

二、141 环形链表

题目描述

给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。

解题思路

1、map或者set

具体思路:新设置一个map,然后循环链表,每次遍历到一个节点的时候,判断当前节点是否在map中存在,如果不存在就把当前节点加入map中,如果存在的话说明之前访问过此节点,也就说明了这条链表有环。

var hasCycle=function(head){
	let map=new Map();
	while(head){
		if(map.has(head)) return true;
		map.set(head,true);
		head=head.next;
	}
	return false;
};
2、快慢指针

准备两个指针fast和slow,循环链表,slow指针初始也指向head,每次循环向前走一步,fast指针初始指向head,每次循环向前两步,如果没有环,则快指针会抵达终点,如果有环,那么快指针会追上慢指针。

var hasCycle=function(head){
	let fast=slow=head;
	while(fast&&fast.next){
		slow=slow.next;
		fast=fast.next.next;
		if(slow==fast) return true;
	}
	return false;
};
3、特殊解法

这是在解答区看到的,很有意思,想记录一下。

var hasCycle = function (head) {
    try {
        JSON.stringify(head)
        //不能循环引用对象;
    } catch{
        return true
    }
    return false
};
//标记法 给遍历过的节点打记号,如果遍历过程中遇到有记号的说明已环
const hasCycle = function(head) {
  while (head) {
    if (head.tag) {
      return true;
    }
    head.tag = true;
    head = head.next;
  }
  return false;
};

三、142 环形链表II

题目描述

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
在这里插入图片描述

解题思路

和141思路一样的,只是返回值变为节点而已。

1、map或set
var detectCycle = function(head) {
    if(head==null) return null;
    let cur=head;
    let map=new Map();
    while(cur){
        if(map.has(cur)) return cur;
        map.set(cur,true);
        cur=cur.next;
    }
    return null;
};
2、快慢指针

这里有个数学公式的推导,我就不赘述了,直接贴一下大佬的解释:a=c+(n-1)(b+c)

var detectCycle = function(head) {
    if(head==null) return null;
    let fast=slow=head;
    while(fast!=null&&fast.next!=null){
        fast=fast.next.next;
        slow=slow.next;
        if(fast==slow) {
            let slow=head;
            while(slow!=fast){
                slow=slow.next;
                fast=fast.next;
            }
            return slow;
        }
    }
    retur
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值