Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法......感兴趣就关注我吧!你定不会失望。
🌈个人主页:主页链接
🌈算法专栏:专栏链接 现已更新完KMP算法,之后我会继续往里填充内容哒。
🌈代码仓库:Gitee链接
🌈点击关注=收获更多优质内容🌈
本题是一道LeetCode上的简单题,使用了模拟、位运算两种方法解题,各位看官往下看。
题解:
先来看看题目:
如果一个密码满足以下所有条件,我们称它是一个 强 密码:
- 它有至少 8 个字符。
- 至少包含 一个小写英文 字母。
- 至少包含 一个大写英文 字母。
- 至少包含 一个数字 。
- 至少包含 一个特殊字符 。特殊字符为:"!@#$%^&*()-+" 中的一个。
- 它 不 包含 2 个连续相同的字符(比方说 "aab" 不符合该条件,但是 "aba" 符合该条件)。
给你一个字符串 password ,如果它是一个 强 密码,返回 true,否则返回 false 。
换成程序语言来看就是:一个字符串里必须要有大小写字母、题给特殊符号、数字,且邻位字符不能相同。
模拟法:
首先来看看比较容易想出来的方法,模拟法:将题目给的条件翻译成代码,较为简单,咱直接上代码。
class Solution { public: bool strongPasswordCheckerII(string password) { if (password.size() < 8)return false; int lower = 0, upper = 0, digit = 0, star = 0, special = 0; for (int i = 0; i < password.size(); i++) { if (i > 0) { char ret = password[i - 1]; if (ret == password[i])return false; } if (isdigit(password[i]))digit = 1; else if (islower(password[i]))lower = 1; else if (isupper(password[i]))upper = 1; else special = 1; } if (lower && upper && digit && special) return true; else return false; } };
这种方法的优点:好想,可能看完题目那一瞬间就能想的出来。
但弊端也是显而易见的:代码冗杂、比较生硬的翻译且因为创建了几个变量来统计相应字符出现的概率,所以占用空间也比较大。
这里不过多解释这种代码,下面着重介绍位运算的方法
位运算:
先来了解一个简单的知识:|运算。有两个数,a=8、b=1,将这两个数都以二进制展开为a=1000,b=0001,这时候a|b就是按照这样一个法则:有1为1其余为0,将他们对齐后是这样,根据我们的法则,最后的结果会是1001
很容易就可以看出|运算可以将一个数展开然后进行计数,相当于每一位都可以是一种情况的出现。这就大大节省了我们需要创建多个变量的空间。
下面进入正题:
一个字符串里必须要有大小写字母、题给特殊符号、数字,且邻位字符不能相同。
分析题干,可以想明白有四种字符要出现,且一种情况不能出现。四种情况:我们设置一个变量改变他的低四位,二进制下的:1111,也就是十进制的:15。表示这四种情况都出现了。
下面上代码
class Solution { public: bool strongPasswordCheckerII(string password) { if(password.size()<8)return -1; int i=0,mask=0; while(i<password.size()) { if(i&&password[i]==password[i-1])return false; if(isdigit(password[i])) mask|=1; else if(islower(password[i])) mask|=2; else if(isupper(password[i])) mask|=4; else mask|=8; i++; } return mask==15; } };
思路:
若字符串长度小于8,则直接return false;
创建计数变量mask。进入循环。
先判断邻位是否存在是否相同这一情况。注意这里可能会存在越位访问的情况:若i=0时,他的邻位就是-1,访问password[-1]是越位访问,所以为了避免这种情况 我们加入了(i&&password)当i为0时此项判断为假直接退出判断,i!=0时这项为真进入下一层判断邻位是否相等。
接下来进行四种情况的判断,若出现则|运算为相应的值,改变二进制下对应位(数字改变0001 小写字母改变0010 大写字母改变0100 特殊符号改变 1000)
当i=字符串长度时退出循环。
之后判定mask是否等于15(1111 四种情况都出现),若真则返回真,若假返回假。
附上LeetCode的成绩:
总结:
利用|位运算判断是否出现一次的情况,大大减少了多次创建变量空间的占用。
完结撒花:
🌈本篇博客的内容【LeetCode每日一题2299. 强密码检验器 II】已经结束。
🌈本篇代码链接:Gitee
🌈LeetCode:题目链接
🌈若对你有些许帮助,可以点赞、关注、评论支持下博主,你的支持将是我前进路上最大的动力。
🌈若以上内容有任何问题,欢迎在评论区指出。若对以上内容有任何不解,都可私信评论询🌈问。
🌈诸君,山顶见!