A password is considered strong if below conditions are all met:

  1. It has at least 6 characters and at most 20 characters.
  2. It must contain at least one lowercase letter, at least one uppercase letter, and at least one digit.
  3. 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;
}
};

参考资料:

https://discuss.leetcode.com/topic/63854/o-n-java-solution-by-analyzing-changes-allowed-to-fix-each-condition/2

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Strong Password Checker 密码强度检查器的更多相关文章

  1. Leetcode: Strong Password Checker

    A password is considered strong if below conditions are all met: It has at least 6 characters and at ...

  2. [Swift]LeetCode420. 强密码检验器 | Strong Password Checker

    A password is considered strong if below conditions are all met: It has at least 6 characters and at ...

  3. mysql 5.6密码强度插件使用

    在mysql 5.6对密码的强度进行了加强,推出了validate_password 插件.支持密码的强度要求. 此插件要求版本:5.6.6 以上版本安装方式: 1.安装插件:(默认安装了插件后,强度 ...

  4. MySQL如何启用密码强度审计【转】

    1.密码验证插件安装 要使服务器可以使用,插件库文件必须位于MySQL插件目录(plugin_dir系统变量指定的目录)中.如有必要,请设置plugin_dir服务器启动时的值, 以告知服务器插件目录 ...

  5. MySQL密码强度验证修改

    MySQL5.6.6版本之后增加了密码强度验证插件validate_password,相关参数设置的较为严格. 影响的语句和函数有:create user,grant,set password,pas ...

  6. 基于规则评分的密码强度检测算法分析及实现(JavaScript)

    简言 用正则表达式做用户密码强度的通过性判定,过于简单粗暴,不但用户体验差,而且用户帐号安全性也差.那么如何准确评价用户密码的强度,保护用户帐号安全呢?本文分析介绍了几种基于规则评分的密码强度检测算法 ...

  7. LeetCode 1051. 高度检查器(Height Checker) 28

    1051. 高度检查器 1051. Height Checker 题目描述 学校在拍年度纪念照时,一般要求学生按照 非递减 的高度顺序排列. 请你返回至少有多少个学生没有站在正确位置数量.该人数指的是 ...

  8. JS脚本检查密码强度

    <html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Con ...

  9. 如何在nopcommerce3.3注册页面添加密码强度检查仪?

    我刚刚完成了nopCommerce注册页面的密码强度检查仪,因为我觉得在电子商务交易平台,安全问题是非常重要的.在注册页面有必要添加一个密码强度检测仪,以便通知用户他们的密码是否足够强大.今天,大多数 ...

随机推荐

  1. 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)

    前言 这篇博客有点长,如果你是高手请您读一读,能对其中的一些误点提出来,以免我误人子弟,并且帮助我提高 如果你是javascript菜鸟,建议您好好读一读,真的理解下来会有不一样的收获 在下才疏学浅, ...

  2. jQuery操作DOM元素

    作为一个后端程序员,也是要和前端页面打交道的.最常见的场景莫过DOM元素操作和前端页面使用AJAX向服务器发送请求.实现上述两个功能当然可以使用原生js来完成,但在实际开发过程中很少这样做,通常会使用 ...

  3. MahApps.Metro使用

    # MahApps.Metro使用 # ## 下载MahApps.Metro ## PM> Install-Package MahApps.Metro ## MainWindow.xaml中添加 ...

  4. [Tool] Open Live Writer 插件更新

    最新插件下载地址:Memento.OLW_V1.0.0.2.7z 零.历史更新记录 2016.11.24 1. 修正 cnblog 语法高亮中的 SQL.Perl 语法高亮异常 下载地址:Mement ...

  5. [C#] 多线程总结(结合进度条)

    线程生命周期(来源 w3cschool) 未启动状态:当线程实例被创建但 Start 方法未被调用时的状况. 就绪状态:当线程准备好运行并等待 CPU 周期时的状况. 不可运行状态: 已经调用 Sle ...

  6. Atitit.数据采集器 dataspider

    Atitit.数据采集器 dataspider /atiplat_cms/src/com/attilax/WebInfoX.java  @dep http://cl.cmcher.com/thread ...

  7. SQLServer修改表字段名称

    EXEC sp_rename 'TableName.[ColumnName]','ColumnNew','COLUMN'

  8. 小程序https Android 安卓可以发request请求,IOS 苹果 发请求失败问题

    如果一个机器可以发送成功,一个机器发送失败,那多半是是域名的https支持的问题 那就用腾讯云的这个ssl测试工具检测下 https://www.qcloud.com/product/ssl#user ...

  9. C#委托的介绍(delegate、Action、Func、predicate)

    委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递.事件是一种特殊的委托. 1.委托的声明 (1). delegate delegate我们常用到的一种声明   Deleg ...

  10. es6

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...