前端算法必刷题系列[69]

305 阅读4分钟

这是我参与更文挑战的第 22 天,活动详情查看 更文挑战

这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。

132. 快乐数 (happy-number)

标签

  • 快慢指针
  • 简单

题目

leetcode 传送门

这里不贴题了,leetcode打开就行,题目大意:

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

「快乐数」定义为:

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

示例 1

输入:19
输出:true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1

示例 2

输入:n = 2
输出:false

基本思路

这题我们的思路如果是暴力求解,就很简单,不赘述,但我们要知道计算机资源优先,栈空间有限,递归层数有限,时间有限,所以在诸多限制下,找寻一个好的算法就非常重要。

快乐数按某种方式计算,如果无限循环,基本上就是表明中间有重复数了,像不像我们之前做的一道题,判断链表是否有环,没错其实我们只要找到数字的规律,判断是否有环形成无限循环就行了。

然后代码需要拆着写

  • 求平方和函数
  • 快慢指针

写法实现

var isHappy = function(n) {
  // 这是计算一个数的各数位平方和的函数 19 => 1^2 + 9^2 = 1 + 81 = 82
  // 82 是作为下一个数
  const calcSum = (num) => {
    let numArr = num.toString().split('')
    // 各位平方之后再加和
    return numArr.map(item => item ** 2).reduce((acc, cur) => acc + cur)
  }

  // 定义快慢指针,一个走一步(算 1 次平方和)
  // 一个走两步(算 2 次平方和),如果中间有相遇就是有环
  let [slow, fast] = [n, n]

  // 先走一次,让两指针错开
  do {
    slow = calcSum(slow);
    fast = calcSum(calcSum(fast));
  } while (fast !== slow)

  return fast === 1
};

console.log(isHappy(19))

133. 验证回文串 (valid-palindrome)

标签

  • 字符串
  • 中等

题目

leetcode 传送门

这里不贴题了,leetcode打开就行,题目大意:

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:

输入: "A man, a plan, a canal: Panama"
输出: true

示例 2:

输入: "race a car"
输出: false

基本思路

主要考察预处理,先把数据处理成能简单判断回文的东西即可。

需要用到这个 api

String.prototype.match()

match() 方法检索返回一个字符串匹配正则表达式的结果

例子

const paragraph = 'The quick 3 brown 66fox jumps over the lazy dog. It barked.';
const regex = /[A-Z]/g;
const found = paragraph.match(regex);

const regex2 = /[0-9]/g;
const num = paragraph.match(regex2)

console.log(found);
// expected output: Array ["T", "I"]
console.log(num)
// ["3", "6", "6"]

语法

str.match(regexp)

参数

regexp

  • 一个正则表达式对象。如果传入一个非正则表达式对象,则会隐式地使用 new RegExp(obj) 将其转换为一个 RegExp 。

  • 如果你没有给出任何参数并直接使用match() 方法 ,你将会得到一个包含空字符串的 Array :[""] 。 返回值

  • 如果使用g标志,则将返回与完整正则表达式匹配的所有结果,但不会返回捕获组。

  • 如果未使用g标志,则仅返回第一个完整匹配及其相关的捕获组(Array)。

其他内容 请看 MDN

实现步骤

  • 因为大小写不管,直接全部转小写或大写
  • 用正则上面的 match api 过滤成只剩字母和数字的字符串
  • 判断是否回文就行,无论是双指针,还是用各种 api 都行(reverse)

关于正则写法请看这篇 正则的基本要点

写法实现

var isPalindrome = function(s) {
  // 预处理 转小写 => 匹配字母数字
  let strArr = s.toLocaleLowerCase().match(/[a-z0-9]/g)
  
  // 注意一个空格也是回文!
  if (!strArr) {
    return true
  }

  return strArr.join('') === strArr.reverse().join('')
};

let str = "A man, a plan, a canal: Panama"
console.log(isPalindrome(str))

另外向大家着重推荐下这个系列的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列

今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 点击此处交个朋友 Or 搜索我的微信号infinity_9368,可以聊天说地 加我暗号 "天王盖地虎" 下一句的英文,验证消息请发给我 presious tower shock the rever monster,我看到就通过,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧

参考