一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
编程世界总是离不了算法
最近在看框架源码时,会有很多算法的实现逻辑,有时候会感到吃力
于是决定蹭着假期,加强算法和数据结构相关的知识
那怎么提升呢?
其实我知道算法这东西没有捷径,多写多练才能提升,于是我开启我的LeetCode
刷题之旅
第一阶段目标是:200
道,每天1
到2
篇
为了不乱,本系列文章目录分为三部分:
- 今日题目:xxx
- 我的思路
- 代码实现
今天题目:420. 强密码检验器
如果一个密码满足下述所有条件,则认为这个密码是强密码: 由至少 6 个,至多 20 个字符组成。 至少包含 一个小写 字母,一个大写 字母,和 一个数字 。 同一字符 不能 连续出现三次 (比如 "...aaa..." 是不允许的, 但是 "...aa...a..." 如果满足其他条件也可以算是强密码)。 给你一个字符串 password ,返回 将 password 修改到满足强密码条件需要的最少修改步数。如果 password 已经是强密码,则返回 0 。
在一步修改操作中,你可以:
插入一个字符到 password , 从 password 中删除一个字符,或 用另一个字符来替换 password 中的某个字符。
示例 1:
输入:password = "a" 输出:5
示例 2:
输入:password = "aA1" 输出:3
示例 3:
输入:password = "1337C0d3" 输出:0
我的思路
假设小写字母,大写字母,数字各需要1个,遍历字符串 已经有小写字母,就不需要小写字母了,设为0。大写字母,数字同理 缺少字符数 = 需要的小写字母数 + 大写字母数 + 数字数
同一字符不能连续出现三次
替换总比删除次数少,所以贪心地优先替换,什么时候删除呢 ?
超过20
一定要删除,怎么删 ?
333a3333a33333aAaAa333333
长度25
,需要删除5
次,优先删除连续3+
次字符
代码实现
var strongPasswordChecker = function(password) {
const n = password.length
let needLowerCase = needUpperCase = needNumber = 1 // 需要小写字母,大写字母和数字
for (let i = 0; i < n; i++) {
const charCode= password.charCodeAt(i)
if (charCode >= 97 && charCode <= 122) needLowerCase = 0 // 已有小写字母
else if (charCode >= 65 && charCode <= 90) needUpperCase = 0 // 已有大写字母
else if (charCode >= 48 && charCode <= 57) needNumber = 0 // 已有数字
}
const needLetter = needLowerCase + needUpperCase + needNumber // 缺少字符数
let delOne = delTwo = replace = 0
for (let i = 2; i < n; i++) { // 遍历找长度 >= 3 的连续字符串
if (password[i - 2] === password[i - 1] && password[i - 1] === password[i]) {
let len = 3
while (i + 1 < n && password[i + 1] === password[i++]) len++ // 连续字符串长度
replace += len / 3 | 0 // 每 3 个字符替换 1 个字符,即可中断 3 个字符的连续
if (len % 3 === 0) delOne++ // 长度是 3 的倍数的字符串数(需删 1 字符)
else if (len % 3 === 1) delTwo++ // 长度 / 3 余数 1 的连续字符串数(需删 2 字符)
} // 长度是 3 倍数,删 1 字符 => 长度 / 3 余数 2 字符串
}// 长度 / 3 余数 1, 删 2 字符 => 长度 / 3 余数 2 字符串,所以,剩下都是余数 2 字符串
if (n < 6) return Math.max(6 - n, needLetter) // 不够 6,优先插入缺少字符
if (n <= 20) return Math.max(replace, needLetter) // 长度合适,优先用缺少字符替换
const needDel = n - 20 // 请参考上面的三轮删除的说明
replace -= Math.min(needDel, delOne) // ↓ 如果还需要删除次数,不够删,按 2:1 置换
if (needDel - delOne > 0) replace -= Math.min((needDel - delOne) / 2 | 0, delTwo)
if (needDel - delOne - delTwo * 2 > 0) replace -= (needDel - delOne - delTwo * 2) / 3 | 0
return needDel + Math.max(replace, needLetter)
};
总结
实现方式其实有很多,这里仅供参考~
由于刚开始刷题,也不知道从哪里刷好,如果前辈们有好的建议,希望不吝赐教,感谢🌹