1318. 或运算的最小翻转次数
直接一位一位做。这道题利于我们理解或运算
a | b | a or b |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 1 |
class Solution {
public:
int minFlips(int a, int b, int c) {
int ans=0;
while(a||b||c) {
int g=(a&1)+(b&1);
int w=c&1;
if(w==0) {
if(g==1) ans++;
else if(g==2) ans+=2;
}
else {
if(g==0) ans++;
}
a>>=1,b>>=1,c>>=1;
}
return ans;
}
};
剑指 Offer II 005. 单词长度的最大乘积
直接循环字符串数组,然后判断每一个单词里面的字母,如果没有相同的用长度乘积来更新答案
class Solution {
public:
int maxProduct(vector<string>& words) {
int ans=0;
for(int i=0;i<words.size();i++) {
for(int k=i+1;k<words.size();k++) {
string word1=words[i],word2=words[k];
int flag=0;
bool st=true;
for(int j=0;j<word2.size();j++) {
int w=word2[j]-'a';
flag|=(1<<w);
}
for(int j=0;j<word1.size();j++) {
int w=word1[j]-'a';
if(flag&(1<<w)) {
st=false;
break;
}
}
if(st) ans=max(ans,(int)word1.size()*(int)word2.size());
}
}
return ans;
}
};
可以看到这篇代码重复计算太多所以时间复杂度太大,所以我们可以预处理一下每一个单词中有哪个字母
class Solution {
public:
int maxProduct(vector<string>& words) {
vector<pair<int,int>>res;
for(auto t:words){
int cnt=0;
for(int i=0;i<t.size();i++){
int a=t[i]-'a';
cnt|=1<<a;
}
res.push_back({cnt,t.size()});
}
int maxn=0;
for(int i=0;i<res.size();i++){
for(int j=i+1;j<res.size();j++){
if((res[i].first&res[j].first)==0) maxn=max(maxn,res[i].second*res[j].second);
}
}
return maxn;
}
};
898. 子数组按位或操作
注意到两个数或出来的值一定大于等于两个数的最大值,所以一个序列或起来的结果一定是所有子序列或起来结果的最大值。利用这个特性剪枝,当达到最大值以后后面的值一定是重复的。
class Solution {
public:
int subarrayBitwiseORs(vector<int>& arr) {
int ans=0,n=arr.size(),flag=0;
for(int i=0;i<n;i++) flag|=arr[i];
unordered_map<int,int>mp;
for(int i=0;i<n;i++) {
int st=0;
for(int j=i;j<n;j++) {
st|=arr[j];
mp[st]++;
if(st==flag) break;
}
}
return mp.size();
}
};