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. Oracle PL/SQL随堂笔记总结

    1.pl/sql编程 2.存储过程 3.函数 4.触发器 5.包 6.pl/sql基础 -定义并使用变量 7.pl/sql的进阶 8.oracle的视图 1.pl/sql编程 1.理解oracle的p ...

  2. c#编程基础之字符串基础

    1.C#中单个的字符串用单引号包含就是char类型,('a'),单引号中放且只能放一个字符 2.单个字符也可以表示为字符串,还可以有长度为0的字符串. 3.使用s.Length属性来获得字符串中的字符 ...

  3. 细说Java主流日志工具库

    概述 在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息. 在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子. 我们先来逐一了解一下主流日志工具. java.util ...

  4. CloudNotes之领域建模篇:领域模型简介

    CloudNotes领域模型还是相对简单的,并不一定需要采用面向领域驱动的设计方法来解决CloudNotes的领域问题.但出于以下几个方面的原因,我还是采用了面向领域驱动的方式来开发CloudNote ...

  5. react初始(1)

    前言:react框架的出现是因为Facebook在建设Instagram交流平台的时候要处理大量的数据流,但是行业流行的MVC框架并不能适合Facebook公司的要求,他们就组织了自己的人力来开发re ...

  6. 从三栏自适应宽度布局到css布局的讨论

    如何实现一个三栏自适应布局,左右各100px,中间随着浏览器宽度自适应? 第一个想到的是使用table布局,设置table的宽度为100%,三个td,第1个和第3个固定宽度为100px,那么中间那个就 ...

  7. 做个简单的RSS订阅(ASP.NET Core),节省自己的时间

    0x01 前言 因为每天上下班路上,午休前,都是看看新闻,但是种类繁多,又要自己找感兴趣的,所以肯定会耗费不少时间. 虽说现在有很多软件也可以订阅一些自己喜欢的新闻,要安装到手机,还是挺麻烦的.所以就 ...

  8. Entity Framework 教程——EF体系结构

    EF体系结构 下图是一张EF体系结构的全景图,让我们单独了解各个组件的用处. EDM (Entity Data Model): EDM由3个主要部分组成,概念模块(Conceptual Model), ...

  9. JDBC_part2_DML以及预编译_编写DBUtil工具类

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! jdbc day02 DML语法 比起插叙语句,没有R ...

  10. Delphi_01_控制台版HelloWorld

    对于Windows下的控制台编程,我相信很多人都不陌生.而C语言开始的著名的“Hello world”程序基本是学习编程的第一步.我想对于 RAD开发,大家熟悉的一般都是GUI编程,而对于consol ...