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. OCP考点实战演练01-备份恢复篇

    本系列宗旨:真正掌握OCP考试中所考察的技能,坚决不做Paper OCP! 实验环境:RHEL 6.4 + Oracle 11.2.0.4 OCP考点实战演练01-备份恢复篇 1.数据库开启归档 2. ...

  2. Docker容器环境下ASP.NET Core Web API应用程序的调试

    本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Docker容器环境下,对ASP.NET Core Web API应用程序进行调试.在 ...

  3. 线程安全性:num++操作为什么也会出问题?

    线程的安全性可能是非常复杂的,在没有充足同步的情况下,由于多个线程中的操作执行顺序是不可预测的,甚至会产生奇怪的结果(非预期的).下面的Tools工具类的plus方法会使计数加一,为了方便,这里的nu ...

  4. UEditor百度富文本编辑器--preview在线预览时头部被挡住的解决方案

    问题截图: 正常情况应该是如下显示: 解决方案: 1.打开ueditor/dialogs/preview/preview.html 2.找到body节点下面这一句 document.getElemen ...

  5. [C1] C1FlexGrid 排除非绑定列的验证效果

    一.前言 前提是 C1FlexGrid 中存在数据绑定列和自定义列(非数据绑定列),此时如果该行编辑后出现排他错误,自定义列也会出现验证结果的红色边框: 但是自定义列如果只是一些按钮操作,提示说明什么 ...

  6. ASP.NET五步打包下载Zip文件

    本文版权归博客园和作者吴双共同所有,转载和爬虫请注明原文地址:www.cnblogs.com/tdws 首先分享几个振奋人心的新闻: 1.谷歌已经宣布加入.NET基金会 2.微软加入Linux基金会, ...

  7. .NET Core全面扫盲贴

    标签: .NETCore Asp.NETCore 1. 前言 2. .NET Core 简介 2.1 .NET Core是什么 2.2 .NET Core的组成 2.3 .NET Core的特性 2. ...

  8. No-args constructor for class X does not exist. Register an InstanceCreator with Gson for this type to fix this problem.

    Gson解析JSON字符串时出现了下面的错误: No-args constructor for class X does not exist. Register an InstanceCreator ...

  9. java web学习总结(二十七) -------------------JSP标签介绍

    一.JSP标签介绍 JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护. 二.JSP常用标签 ...

  10. 手机端访问web调用数字键盘。

    转自  http://www.webkfa.com/one4/w1937.html 最近在做手机页面时,遇到数字输入的键盘的问题,之前的做法只是一刀切的使用 type="tel", ...