《算法零基础100讲》(第45讲) 位运算 (位或) 进阶【题解】

本文深入探讨了三种位运算的应用:在寻找最大单词长度乘积问题中,利用位运算高效地判断两单词是否有公共字母;在最小翻转次数问题中,通过位翻转实现或运算达到目标值;以及在子数组按位或操作中,计算不同子数组的按位或结果数量。通过实例解析,展示了位运算在解决数组问题中的强大能力。
摘要由CSDN通过智能技术生成

目录

传送门

课后习题

318.最大单词长度乘积

1318.或运算的最小翻转次数

898.子数组按位或操作


传送门

《算法零基础100讲》(第45讲) 位运算 (位或) 进阶_英雄哪里出来-CSDN博客位运算 之 位或 进阶https://blog.csdn.net/WhereIsHeroFrom/article/details/121710831

课后习题

318.最大单词长度乘积

318. 最大单词长度乘积icon-default.png?t=LA92https://leetcode-cn.com/problems/maximum-product-of-word-lengths/

 题目描述:

给定一个字符串数组 words,找到 length(word[i]) * length(word[j]) 的最大值,并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词,返回 0

int maxProduct(char ** words, int wordsSize){
    /*
        因为 int 32位,而字母就26个,所以用一个int可以表示一个字符串中所有出现的字母
    */
    int *hash = (int*)malloc(sizeof(int)*wordsSize);
    int i,j,ans = 0;
    for(i=0; i<wordsSize; ++i){
        int len = strlen(words[i]);
        hash[i] = 0;
        for(j=0; j<len; ++j){
            hash[i] |= 1<<(words[i][j]-'a');   //出现就将对应的位 置1
        }
            
    }
    for(i=0; i<wordsSize; ++i){
        for(j=i+1; j<wordsSize; ++j)
            if((hash[i] & hash[j]) == 0){       //如果 & 为0,则说明没有同时为 1 的位,即没有公共字母
                int t = strlen(words[i]) * strlen(words[j]);
                printf("%d",t);
                if(t > ans)
                    ans = t;
            }
    }
    return ans;
}

1318.或运算的最小翻转次数

1318. 或运算的最小翻转次数icon-default.png?t=LA92https://leetcode-cn.com/problems/minimum-flips-to-make-a-or-b-equal-to-c/

 题目描述:

给你三个正整数 a、b 和 c。

你可以对 a 和 b 的二进制表示进行位翻转操作,返回能够使按位或运算   a OR b == c  成立的最小翻转次数。

「位翻转操作」是指将一个数的二进制表示任何单个位上的 1 变成 0 或者 0 变成 1 。


int GetBit(int x,int i){
    return (x>>i) & 1;          //取x第 i 位
}

int minFlips(int a, int b, int c){
    int i,ans = 0;
    for(i=0;i<31;++i){
        int ai = GetBit(a,i);
        int bi = GetBit(b,i);
        int ci = GetBit(c,i);
        if((ai | bi) == ci)         //如果相等 则无需翻转
            continue;
        if(ci == 0)                 // 如果目标位0 则需要将a、b都置0
            ans += ai+bi;
        else if(ci == 1)            // 只需要其中一个置 1就行了
            ans += 1;
    }
    return ans;
}

898.子数组按位或操作

898. 子数组按位或操作icon-default.png?t=LA92https://leetcode-cn.com/problems/bitwise-ors-of-subarrays/

 题目描述:

我们有一个非负整数数组 A。

对于每个(连续的)子数组 B = [A[i], A[i+1], ..., A[j]] ( i <= j),我们对 B 中的每个元素进行按位或操作,获得结果 A[i] | A[i+1] | ... | A[j]。

返回可能结果的数量。 (多次出现的结果在最终答案中仅计算一次。)

//看到数据范围10^9,那得开多大空间,直接换c++做了

class Solution {
public:
    int subarrayBitwiseORs(vector<int>& arr) {
        unordered_set<int> st;
        int Max=0;
        for(int i:arr){
            Max |= i;           //求出最大值
        }
        for(int i=0;i<arr.size();++i){
            int num = arr[i];
            st.insert(num);             
            for(int j=i+1;j<arr.size();++j){
                num |= arr[j];
                st.insert(num);
                if(num == Max)  //如果已经达到最大值,再或下去也不会有新的结果 直接退出
                    break;          //没有这个会超时,我试了
            }
        }
        return st.size();
    }
};

每天打卡打卡打卡!!!

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周日加一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值