[LeetCode] Strong Password Checker 密码强度检查器
A password is considered strong if below conditions are all met:
- It has at least 6 characters and at most 20 characters.
- It must contain at least one lowercase letter, at least one uppercase letter, and at least one digit.
- It must NOT contain three repeating characters in a row ("...aaa..." is weak, but "...aa...a..." is strong, assuming other conditions are met).
Write a function strongPasswordChecker(s), that takes a string s as input, and return the MINIMUM change required to make s a strong password. If s is already strong, return 0.
Insertion, deletion or replace of any one character are all considered as one change.
这道题给了我们一个密码串,让我们判断其需要多少步修改能变成一个强密码串,然后给定了强密码串的条件,长度为6到20之间,必须含有至少一个的小写字母,大写字母,数字,而且不能有连续三个相同的字符,给了我们三种修改方法,任意一个位置加入字符,删除字符,或者是置换任意一个字符,让我们修改最小的次数变成强密码串。这道题定义为Hard真是名副其实,博主光是看大神的帖子都看了好久,这里主要是参考了大神fun4LeetCode的帖子,个人感觉这个算是讲的十分清楚的了,这里就照搬过来吧。首先我们来看非强密码串主要有的三个问题:
1. 长度问题,当长度小于6的时候,我们要通过插入字符来补充长度,当长度超过20时,我们要删除字符。
2. 缺失字符或数字,当我们缺少大写,小写和数字的时候,我们可以通过插入字符或者替换字符的方式来补全。
3. 重复字符,这个也是本题最大的难点,因为插入,删除,或者置换都可以解决重复字符的问题,比如有一个字符串"aaaaa",我们可以用一次置换,比如换掉中间的字符'a';或者两次插入字符,在第二个a和第四个a后面分别插入一个非a字符;或者可以删除3个a来解决重复字符的问题。由于题目要求我们要用最少的步骤,那么显而易见置换是最高效的去重复字符的方法。
我们通过举例观察可以知道这三种情况并不是相互独立的,一个操作有时候可以解决多个问题,比如字符串"aaa1a",我们在第二个a后面增加一个'B',变为"aaBa1a",这样同时解决了三个问题,即增加了长度,又补充了缺失的大写字母,又去掉了重复,所以我们的目标就是尽可能的找出这种能解决多种问题的操作。由于情况三(重复字符)可以用三种操作来解决,所以我们分别来看能同时解决情况一和情况三,跟同时解决情况二和情况三的操作。对于同时解决情况一和情况二的操作如果原密码串长度小于6会有重叠出现,所以我们要分情况讨论:
当密码串长度小于6时,情况一和情况二的操作步骤可以完全覆盖情况三,这个不难理解,因为这种情况下重复字符个数的范围为[3,5],如果有三个重复字符,那么增加三个字符的操作可以同时解决重复字符问题("aaa" -> "a1BCaa";如果有四个重复字符,那么增加二个字符的操作也可以解决重复问题("aaaa" -> "aa1Baa");如果有五个重复字符,那么增加和置换操作也同时解决重复问题("aaaaa" -> "aa1aaB")。所以我们就专心看最少多少步能同时解决情况一和情况二,首先我们计算出当前密码串需要补几个字符才能到6,补充字符的方法只能用插入字符操作,而插入字符操作也可以解决情况二,所以当情况二的缺失种类个数小于等于diff时,我们不用再增加操作,当diff不能完全覆盖缺失种类个数时,我们还应加上二者的差值。
当密码串长度大于等于6个的时候,这种情况就比较复杂了,由于目前字符串的长度只可能超标不可能不达标,所以我们尽量不要用插入字符操作,因为这有可能会使长度超过限制。由于长度的不确定性,所以可能会有大量的重复字符,那么解决情况三就变得很重要了,由于前面的分析,替换字符是最高效的解法,但是这种方法没法解决情况一,因为长度超标了的话,再怎么替换字符,也不会让长度减少,但是我们也不能无脑删除字符,这样不一定能保证是最少步骤,所以在解决情况三的时候还要综合考虑到情况一,这里用到了一个trick (很膜拜大神能想的出来),对于重复字符个数k大于等于3的情况,我们并不是直接将其删除到2个,而是先将其删除到最近的(3m+2)个,那么如果k正好被3整除,那么我们直接变为k-1,如果k除以3余1,那么变为k-2。这样做的好处是3m+2个重复字符可以最高效的用替换m个字符来去除重复。那么下面我们来看具体的步骤,首先我们算出超过20个的个数over,我们先把over加到结果res中,因为无论如何这over个删除操作都是要做的。如果没超过,over就是0,用变量left表示解决重复字符最少需要替换的个数,初始化为0。然后我们遍历之前统计字符出现个数的数组,如果某个字符出现个数大于等于3,且此时over大于0,那么我们将个数减为最近的3m+2个,over也对应的减少,注意,一旦over小于等于0,不要再进行删除操作。如果所有重复个数都减为3m+2了,但是over仍大于0,那么我们还要进一步的进行删除操作,这回每次直接删除3m个,直到over小于等于0为止,剩下的如果还有重复个数大于3的字符,我们算出置换字符需要的个数直接加到left中即可,最后我们比较left和missing,取其中较大值加入结果res中即可,参见代码如下:
class Solution {
public:
int strongPasswordChecker(string s) {
int res = , n = s.size(), lower = , upper = , digit = ;
vector<int> v(n, );
for (int i = ; i < n;) {
if (s[i] >= 'a' && s[i] <= 'z') lower = ;
if (s[i] >= 'A' && s[i] <= 'Z') upper = ;
if (s[i] >= '' && s[i] <= '') digit = ;
int j = i;
while (i < n && s[i] == s[j]) ++i;
v[j] = i - j;
}
int missing = (lower + upper + digit);
if (n < ) {
int diff = - n;
res += diff + max(, missing - diff);
} else {
int over = max(n - , ), left = ;
res += over;
for (int k = ; k < ; ++k) {
for (int i = ; i < n && over > ; ++i) {
if (v[i] < || v[i] % != (k - )) continue;
v[i] -= k;
over -=k;
}
}
for (int i = ; i < n; ++i) {
if (v[i] >= && over > ) {
int need = v[i] - ;
v[i] -= over;
over -= need;
}
if (v[i] >= ) left += v[i] / ;
}
res += max(missing, left);
}
return res;
}
};
参考资料:
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Strong Password Checker 密码强度检查器的更多相关文章
- Leetcode: Strong Password Checker
A password is considered strong if below conditions are all met: It has at least 6 characters and at ...
- [Swift]LeetCode420. 强密码检验器 | Strong Password Checker
A password is considered strong if below conditions are all met: It has at least 6 characters and at ...
- mysql 5.6密码强度插件使用
在mysql 5.6对密码的强度进行了加强,推出了validate_password 插件.支持密码的强度要求. 此插件要求版本:5.6.6 以上版本安装方式: 1.安装插件:(默认安装了插件后,强度 ...
- MySQL如何启用密码强度审计【转】
1.密码验证插件安装 要使服务器可以使用,插件库文件必须位于MySQL插件目录(plugin_dir系统变量指定的目录)中.如有必要,请设置plugin_dir服务器启动时的值, 以告知服务器插件目录 ...
- MySQL密码强度验证修改
MySQL5.6.6版本之后增加了密码强度验证插件validate_password,相关参数设置的较为严格. 影响的语句和函数有:create user,grant,set password,pas ...
- 基于规则评分的密码强度检测算法分析及实现(JavaScript)
简言 用正则表达式做用户密码强度的通过性判定,过于简单粗暴,不但用户体验差,而且用户帐号安全性也差.那么如何准确评价用户密码的强度,保护用户帐号安全呢?本文分析介绍了几种基于规则评分的密码强度检测算法 ...
- LeetCode 1051. 高度检查器(Height Checker) 28
1051. 高度检查器 1051. Height Checker 题目描述 学校在拍年度纪念照时,一般要求学生按照 非递减 的高度顺序排列. 请你返回至少有多少个学生没有站在正确位置数量.该人数指的是 ...
- JS脚本检查密码强度
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Con ...
- 如何在nopcommerce3.3注册页面添加密码强度检查仪?
我刚刚完成了nopCommerce注册页面的密码强度检查仪,因为我觉得在电子商务交易平台,安全问题是非常重要的.在注册页面有必要添加一个密码强度检测仪,以便通知用户他们的密码是否足够强大.今天,大多数 ...
随机推荐
- 用 jQuery.ajaxSetup 实现对请求和响应数据的过滤
不知道同学们在做项目的过程中有没有相同的经历呢?在使用 ajax 的时候,需要对请求参数和响应数据进行过滤处理,比如你们觉得就让请求参数和响应信息就这么赤裸裸的在互联网里来回的穿梭,比如这样: 要知道 ...
- Android来电监听和去电监听
我觉得写文章就得写得有用一些的,必须要有自己的思想,关于来电去电监听将按照下面三个问题展开 1.监听来电去电有什么用? 2.怎么监听,来电去电监听方式一样吗? 3.实战,有什么需要特别注意地方? 监听 ...
- Angular2 小贴士 NgModule 模块
angular2 具有了模块的概念,响应了后台程序的号召,高内聚 低耦合.模块就是用来进行封装,进行高内聚 低耦合的功能. 其实各人认为ng2 的模块和.net的工程类似,如果要使用模块中定义的功能 ...
- java基础知识 多线程
package org.base.practise9; import org.junit.Test; import java.awt.event.WindowAdapter; import java. ...
- .NET Core 2.0版本预计于2017年春季发布
英文原文: NET Core 2.0 Planned for Spring 2017 微软项目经理 Immo Landwerth 公布了即将推出的 .NET Core 2.0 版本的细节,该版本预计于 ...
- 了解AIDL
1.什么是AIDL? Android Interface Definition Lauguage(android接口描述语言)是一个IDL语言. 2.AIDL的作用? 背景:在android平台 中, ...
- 在网站开发中很有用的8个 jQuery 效果【附源码】
jQuery 作为最优秀 JavaScript 库之一,改变了很多人编写 JavaScript 的方式.它简化了 HTML 文档遍历,事件处理,动画和 Ajax 交互,而且有成千上万的成熟 jQuer ...
- Why AlloyFinger is so much smaller than hammerjs?
AlloyFinger is the mobile web gesture solution at present inside my company, major projects are in u ...
- NSDateFormatter 时间格式转换
NSString *strDate = @“Wed Apr ::”; NSDateFormatter *dateFomatter =[[NSDateFormatter alloc] init]; [d ...
- iOS 正确选择图片加载方式
正确选择图片加载方式能够对内存优化起到很大的作用,常见的图片加载方式有下面三种: //方法1 UIImage *imag1 = [UIImage imageNamed:@"image.png ...