算法——位运算

1.二进制加法

https://leetcode.cn/problems/JFETK5/
思路一 (模拟):

#include<iostream>
#include<algorithm>

using namespace std;
/*
给定两个 01 字符串 a 和 b ,请计算它们的和,并以二进制字符串的形式输出。

输入为 非空 字符串且只包含数字 1 和 0。

 
示例 1:

输入: a = "11", b = "10"
输出: "101"
示例 2:

输入: a = "1010", b = "1011"
输出: "10101"

思路之:模拟
(1)翻转字符串使低位对其
 (2)创建结果字符串
(3)s1.at(i)按位判断 加到临时变量上
(4)% /作进位和该位的结果计算
(5)超出a b长度的部分算0 结果最高位的0去除 然后翻转回来
时间复杂度:O(n),这里的时间复杂度来源于顺序遍历 a和 b。
空间复杂度:O(1),定义的一些变量
*/

/*
class Solution {
public:
    string addBinary(string a, string b) {
        int lengtha = a.size();
        int lengthb = b.size();
        int n = max(lengtha, lengthb);
        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());

        int temp = 0;
        string res(n + 1, '0');
        for (int i = 0; i < n+1; i++) {
            if (i < a.size())
            {
                temp += (a.at(i) == '1') ? 1 : 0;

            }
            else {
                temp += 0;
            }
            if (i < b.size())
            {
                temp += (b.at(i) == '1') ? 1 : 0;
            }
            else {
                temp += 0;
            }

            res = (temp%2 == 1) ? res.replace(i, 1, "1") : res.replace(i, 1, "0");

            temp = temp / 2;


        }
        
        if (res.at(n) == '0')
            res = res.substr(0, n);

          reverse(res.begin(), res.end());

        return res;

    }
};
*/
/*
int main() {

    Solution sol;
    //string s1(sol.addBinary("0", "0"));
    string s1(sol.addBinary("1010", "10111"));

    cout << s1 << endl;
	return 0;
}*/
模拟思路的参考答案
class Solution {
public:
    string addBinary(string a, string b) {
        string ans;
        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());

        int n = max(a.size(), b.size()), carry = 0;
        for (size_t i = 0; i < n; ++i) {
            carry += i < a.size() ? (a.at(i) == '1') : 0;
            carry += i < b.size() ? (b.at(i) == '1') : 0;
            ans.push_back((carry % 2) ? '1' : '0');
            carry /= 2;
        }

        if (carry) {
            ans.push_back('1');
        }
        reverse(ans.begin(), ans.end());

        return ans;
    }
};

思路二(位运算):
如果不允许加减乘除可以用位运算的思路
看一眼即可
首先转换成二进制数字 不太明白
在这里插入图片描述

2.前 n 个数字二进制中 1 的个数
给定一个非负整数 n ,请计算 0 到 n 之间的每个数字的二进制表示中 1 的个数,并输出一个数组。

示例 1:

输入: n = 2
输出: [0,1,1]
解释: 
0 --> 0
1 --> 1
2 --> 10
示例 2:

输入: n = 5
输出: [0,1,1,2,1,2]
解释:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101

我的思路 模拟运算。。。

class Solution {
public:
    int number1(int n){
        int cnt=0;
        while(1)
        {
            
            cnt+=(n%2==1)?1:0;
            n=n/2;
            if(n==0||n==1)
           {
               if(n==1)
               cnt+=1;

            break;
           }


        }
        return cnt;
    }
    vector<int> countBits(int n) {
        vector<int> a;
        int i=0;
       
            for(int i=0;i<=n;i++)
            a.push_back(number1(i));
        
        return a;

    }
};

思路二:一比特数算法

方法一:
Brian Kernighan 算法
最直观的做法是对从 0 到 n 的每个整数直接计算「一比特数」。
每个 int 型的数都可以用 32 位二进制数表示,
只要遍历其二进制表示的每一位即可得到 11 的数目。

利用 Brian Kernighan 算法,可以在一定程度上进一步提升计算速度。
Brian Kernighan 算法的原理是:对于任意整数 x,
令 x=x & (x−1),该运算将 xx 的二进制表示的最后一个 1 变成 0。
因此,对 x 重复该操作,直到 x 变成 0,则操作次数即为 x 的「一比特数」。

对于给定的 n,计算从 00 到 nn 的每个整数的「一比特数」的时间都不会超过 O(logn),因此总时间复杂度为
O(nlogn)
class Solution {
public:
    int countOnes(int x) {
        int ones = 0;
        while (x > 0) {
            x &= (x - 1);
            ones++;
        }
        return ones;
    }

    vector<int> countBits(int n) {
        vector<int> bits(n + 1);
        for (int i = 0; i <= n; i++) {
            bits[i] = countOnes(i);
        }
        return bits;
    }
};
3.剑指 Offer II 005. 单词长度的最大乘积

给定一个字符串数组 words,请计算当两个字符串 words[i] 和 words[j] 不包含相同字符时,它们长度的乘积的最大值。假设字符串中只包含英语的小写字母。如果没有不包含相同字符的一对字符串,返回 0。

示例 1:

输入: words = [“abcw”,“baz”,“foo”,“bar”,“fxyz”,“abcdef”]
输出: 16
解释: 这两个单词为 “abcw”, “fxyz”。它们不包含相同字符,且长度的乘积最大。
示例 2:

输入: words = [“a”,“ab”,“abc”,“d”,“cd”,“bcd”,“abcd”]
输出: 4
解释: 这两个单词为 “ab”, “cd”。

class Solution {
public:
    int maxProduct(vector<string>& words) {
        int length = words.size();
        vector<int> masks(length);
        for (int i = 0; i < length; i++) {
            string word = words[i];
            int wordLength = word.size();
            for (int j = 0; j < wordLength; j++) {
                masks[i] |= 1 << (word[j] - 'a');
            }
        }
        int maxProd = 0;
        for (int i = 0; i < length; i++) {
            for (int j = i + 1; j < length; j++) {
                if ((masks[i] & masks[j]) == 0) {
                    maxProd = max(maxProd, int(words[i].size() * words[j].size()));
                }
            }
        }
        return maxProd;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值