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.
refer to https://discuss.leetcode.com/topic/63854/o-n-java-solution-by-analyzing-changes-allowed-to-fix-each-problem
http://www.cnblogs.com/grandyang/p/5988792.html
这道题给了我们一个密码串,让我们判断其需要多少步修改能变成一个强密码串,然后给定了强密码串的条件,长度为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中即可,参见代码如下:
另外,关于35-37行讲解:
@sunvssoon Hi sunvssoon. After we've transformed all repeating characters into (3m + 2) form, if the total length is still greater than 20 (i.e., over_len > 0), then we have no choice but to start deleting characters to fix the repeating character problem.
Note now the total number of repeating characters at each position is arr[i], and to completely fix it only by deletion will take at least (arr[i] - 2) changes (example, to fix "aaaaa" by deletion, we need to delete at least 3 'a's, which is the total length minus 2). So "need" here is the minimum number of changes needed to fix the repeating character problem by deletion only.
For the following expression, "arr[i] -= over_len", it's just a convenient way to reset the number of repeating characters at that position after deletion. Strictly speaking we should distinguish the two cases when the remaining deletions can totally fix the repeating problem or they cannot. For the former we should reset "arr[i]" to 2 while for the latter it should be "arr[i] - over_len". But we can combine these two cases into one expression "arr[i] - over_len", since for the former, as the problem can be totally fixed by deletion, we must have "over_len >= arr[i] - 2", which means "arr[i] - over_len" will be less than 3, so they will no longer be considered as repeating character problem later.
As to the last expression, "over_len -= need", since fixing each repeating character problem will take at least "need" deletions, we need to reduce "over_len" by that amount to get the remaining available number of deletions.
public class Solution {
public int strongPasswordChecker(String s) {
int res = 0, a = 1, A = 1, d = 1;
char[] carr = s.toCharArray();
int[] arr = new int[carr.length];
for (int i = 0; i < arr.length;) {
if (Character.isLowerCase(carr[i])) a = 0;
if (Character.isUpperCase(carr[i])) A = 0;
if (Character.isDigit(carr[i])) d = 0;
int j = i;
while (i < carr.length && carr[i] == carr[j]) i++;
arr[j] = i - j;
}
int total_missing = (a + A + d);
if (arr.length < 6) {
res += total_missing + Math.max(0, 6 - (arr.length + total_missing));//优先insert missing element,满6之后采用replace,
} else {
int over_len = Math.max(arr.length - 20, 0), left_over = 0;
res += over_len;
for (int k = 1; k < 3; k++) { //全部重复三次以上的元素delete成3m+2,
for (int i = 0; i < arr.length && over_len > 0; i++) {
if (arr[i] < 3 || arr[i] % 3 != (k - 1)) continue;//关注余数为0的情况时,余数为1,2都要skip,关注余数为1的情况时,余数为0,2都要skip
arr[i] -= Math.min(over_len, k);//余数为1,就减二;余数为0,就减一
over_len -= k;
}
}
for (int i = 0; i < arr.length; i++) {//分析over_len如果还>0的情况
if (arr[i] >= 3 && over_len > 0) {
int need = arr[i] - 2; //目标想要被减除的量,然而over_len不一定还有这么多
arr[i] -= over_len; //简便写法,其实是减完之后arr[i]==2(over_len>=need,只减need这么多) 和 arr[i]==arr[i]-over_len(over_len<need)两种情况
over_len -= need;
}
if (arr[i] >= 3) left_over += arr[i] / 3; //这部分需要用replace来消除剩余重复情况
}
res += Math.max(total_missing, left_over); //replace的时候可以同时解决missing element的情况
}
return res;
}
}
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 ...
- leetcode 1051. Height Checker
Students are asked to stand in non-decreasing order of heights for an annual photo. Return the minim ...
- LeetCode All in One 题目讲解汇总(持续更新中...)
终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 477 Total Hamming Distance ...
- Swift LeetCode 目录 | Catalog
请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift 说明:题目中含有$符号则为付费题目. 如 ...
- LeetCode All in One题解汇总(持续更新中...)
突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...
- All LeetCode Questions List 题目汇总
All LeetCode Questions List(Part of Answers, still updating) 题目汇总及部分答案(持续更新中) Leetcode problems clas ...
- leetcode 学习心得 (2) (301~516)
源代码地址:https://github.com/hopebo/hopelee 语言:C++ 301. Remove Invalid Parentheses Remove the minimum nu ...
- LeetCode All in One 题目讲解汇总(转...)
终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 如果各位看官们,大神们发现了任何错误,或是代码无法通 ...
随机推荐
- 【wikioi】1003 电话连线
题目链接 算法: 最小生成树 PS:被卡过2天(中间的时间没去做).日期:2013-09-13 13:49:47 ~ 2013-09-17 13:01:07 此题为基础题 刚开始学图论时只会用Krus ...
- PHP面向对象学习四 类的关键字
1.关键字:final 用来定义类和方法的一个重要关键字,当定义类的时候该类将不能被继承, 当用来定义方法的时候该方法将不能被重载 2.关键字:static 用来定义类的静态属性或方法,可以在类未被实 ...
- OLTP与OLAP的介绍
OLTP与OLAP的介绍 数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing).联机分析处理OLAP(On-Line Analytical ...
- springmvc入门基础之注解和参数传递
一.SpringMVC注解入门 1. 创建web项目2. 在springmvc的配置文件中指定注解驱动,配置扫描器 <!-- mvc的注解驱动 --> <mvc:annotation ...
- 看好你的门-客户端传数据-用java修改referer
1.简单说明 Referer.origin用来表明,浏览器向WEB服务器表明自己来自哪里.但是就它本身而言,并非完全安全. 写一个例子,可以任意修改http信息头中的referer.origin 2. ...
- html5用到的js
1.Zepto.js 是专门为现代智能手机浏览器退出的 Javascript 框架, 拥有和jQuery相似的语法, 但是和jQuery相比下来, 他有很多优点, 大小方面 , 压缩后的 zepto. ...
- linux笔记三-------根目录相关说明
1. /bin binary二进制文件,可执行程序文件 ls su pwd cd 内部文件是一些指令信息 2. /sbin super bin ...
- thinkphp框架3.2的cookie删除问题记录
在使用框架删除cookie时,发现cookie(null)不起作用.后来查看官网相关信息,看到了讨论http://www.thinkphp.cn/bug/2602.html
- php内网探测脚本&简单代理访问
<?php $url = isset($_REQUEST['u'])?$_REQUEST['u']:null; $ip = isset($_REQUEST['i'])?$_REQUEST['i' ...
- html - 自动播放音乐
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...