JS链表-力扣141及201题|刷题打卡

154 阅读4分钟

一直都知道算法对程序员来说很重要,但是自己刷题一直都是断断续续,很难坚持,最近报了个算法班,老师带着刷题,轻松不少,今天来做个小总结。

链表数据结构

关于链表数据结构的知识,我们很多人应该在大学的数据结构课程中就已经学习过了,这里做个简单介绍。

链表,顾名思义就是一种如同铁链般的结构,一环扣一环,每一个链节点都会被上一个节点连接,而它本身也会去链接下一个节点,如图:

每一个节点,分为存储该节点数据的数据域和指向下一个节点的指针域。在JS中,我们可以这么来表示一个链表结构:

class ListNode{
	constructor(val){
    	this.val = val // 数据域
    	this.next = null // 指针域
    }
}
const Node1 = new ListNode(1) // 1 -> null
const Node2 = new ListNode(3) // 2 -> null
Node1.next = Node2
console.log(Node1) // 1 -> 2 -> null

下面来看两个链表相关的题:

141. 环形链表

一、题目描述

给定一个链表,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。如下图: 二、解题思路

这道题可以用双指针来完成,即我们定义两个指针,这两个指针,一个每次向链表的尾部移动一个节点,另一个每次移动两个节点,此时: 1.如果不是环形链表,指针最终会指向null. 2.如果是环形链表,两个指针最终都会进入环中,同时因为指针移动速度不同,快的指针最终会追上慢的指针。 所以我们只需要判断指针是否是null,以及两个指针是否会指向同一个内存。 代码如下:

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {boolean}
 */
var hasCycle = function(head) {
    if(head === null || head.next === null) return false  //链表为null,或链表只有一个节点都不会是环形链表
    let p = q = head
    do{
        p = p.next
        q = q.next.next
    }while(q != p && q && q.next )
    return q === p  //如果不相等,说明节点循环结束,没有环,相等则说明,两个指针在环中相遇
};

202. 快乐数

一、题目描述

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」定义为:

对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。 如果 可以变为  1,那么这个数就是快乐数。 如果 n 是快乐数就返回 true ;不是,则返回 false 。

二、解题思路

这道题我一开始看,真没和链表联系在一起来,老师讲解后,才明白。 我们求每一个数的每个数字的平方和,就可以把这个数和它每个位置平方和这个数联系起来,从而形成链表般的结构,这样我们就可以如上面141题的思路判断是否是环形链表来做题了。

1.如果这个数字如题中说的最终无限循环,始终不到一,那么两个指针会相遇,所以它就是个环形链表。我们可以结束遍历,同时判定出该数字不是快乐数。

2.如果遍历过程中指针指向了数字1,那么就可以得出结论,该数字是快乐数。

代码如下:

/**
 * @param {number} n
 * @return {boolean}
 */
var isHappy = function(n) {
    if(n === 1) return true
    let p = getnext(n),q = getnext(getnext(n))
    while(q!=p && q!= 1){
        p = getnext(p)
        q = getnext(getnext(q))
    }
    // 循环结束是因为无限循环导致指针相遇的话,q != 1,返回false
    // 如果是因为出现了1,那么返回true
    return q === 1
};
function getnext(num){ // 求下一个数字 & 下一个链表节点
    let z = 0
    while(num){
        z += ((num%10)*(num%10))
        num = Math.floor(num/10)
    }
    return z
}

总结

其实这个链表结构,在JS中也不是很陌生的东西,JS的原型链,就是这种类似的结构,懂原型链的话,就很容易理解。对象中的一个属性作为指针,指向另一个对象,即给这个属性赋上另一个引用类型的对象,这样就是一个链表了

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情