420. Strong Password Checker

本文介绍了一种算法,用于检查并修正弱密码使其达到强密码标准。该算法确保密码长度在6到20个字符之间,包含至少一个小写字母、一个大写字母和一个数字,并避免三个相同字符连续出现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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,且要同时有大写字母,小写字母和数字(记缺少种类个数为needs),求最少的操作数是多少。一次操作只能是增删改一个字符。因为一个操作可能使得同时满足几个条件,比如112aaa223,只需要改变aaaa中间的a为一个大写字母,就能满足条件,所以要考虑的比较多。这里按照字符串长度n,分三种情况考虑。

第一种情况是n<6。这种情况是肯定要添加字符操作的,而不需要删除操作。所以可以在添加字符的同时满足另外两个条件。计算needs和使得不出现连续三个字符的改变数chRepeat(对每个连续块每三个字符要修改一个,所以chRepeat=连续块大小/3,这里连续块指的是连续数大于2),因为这两个操作也是互相影响的,即在破坏三连续的同时通过修改字符满足符合种类要求,反过来也行,所以求needs和chRepeat的最大值即可。最后因为添加字符和上述两个操作也是互相影响的,所以求添加数和前面的最大值的最大值即可。

第二种情况是6<=n<=20。这种情况不需要添加和删除,像上面一样求needs和chRepeat的最大值即可。

第三种情况是n>20,比较复杂。这种情况需要删除字符,不需要添加。删除字符和添加不一样的是,要删除到只剩下两个连续字符才能破坏三连续,而且种类只能靠修改来获得。为了使得操作数最少,也就是使得删除字符到n=20后,需要修改的字符最少。从一个例子来看,aaaabbaaabbaaa123456A,n=21,只能删除一个字符,有三个连续块。如果删除4个a中的1个,后面还要修改3个连续块中的3个a,操作数为4;如果删除3个a中的1个,剩下2个连续块,修改2个a即可,操作数为3。所以优先修改(连续块大小%3)比较小的块会比较好。遵守这个原则,每个块删除到(连续块大小%3)=2就转向删除别的块(如果删除数还够的话)。直到删除数为0,统计剩下的连续块需要修改的次数,和needs比较取最大值(这两个操作还是互相影响的),加上删除数,就得到答案。


代码:

class Solution
{
public:
	int strongPasswordChecker(string s)
	{
		int needUpper = 1, needLower = 1, needDigit = 1;
		vector<int>repeat;
		int cnt = 1, n = s.size(), needs = 0 ,chRepeat = 0;

		if(n == 0) return 6;

		for(int i = 0; i < n; ++i)
		{
			if(isupper(s[i])) needUpper = 0;
			if(islower(s[i])) needLower = 0;
			if(isdigit(s[i])) needDigit = 0;

			if(i == 0) continue;

			if(s[i] == s[i - 1])
			{
				++cnt;
			}
			else
			{
				if(cnt >= 3)
				{
					chRepeat += cnt / 3;
					repeat.push_back(cnt);
				}
				cnt = 1;
			}
		}
		if(cnt >= 3)
		{
			chRepeat += cnt / 3;
			repeat.push_back(cnt);
		}
		needs = needUpper + needLower + needDigit;

		if(n < 6)
		{
			return max(6 - n, max(chRepeat, needs));
		}
		else if(n <= 20)
		{
			return max(needs, chRepeat);
		} 
		else
		{
			int r = n - 20;
			chRepeat = 0;
			auto cmp = [](const int n1, const int n2){return (n1 % 3) < (n2 % 3);};
			sort(repeat.begin(), repeat.end(), cmp);

			for(int i = 0; i < repeat.size(); ++i)
			{
				if(repeat[i] % 3 == 2) break;
				int tmp = (repeat[i] % 3) + 1;
				if(r >= tmp) 
				{
					repeat[i] -= tmp;
					r -= tmp;
				}
				else
				{
					repeat[i] -= r;
					r = 0;
					break;
				}
			}
			for(int i = 0; i < repeat.size(); ++i)
			{
				int tmp = ((repeat[i] - 2) / 3) * 3;
				if(r != 0 && r >= tmp) 
				{
					r -= tmp;
				}
				else
				{
					chRepeat += (repeat[i] - r) / 3;
					r = 0;
				}
			}
			return n - 20 + max(needs, chRepeat);
		}
	}
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值