0
点赞
收藏
分享

微信扫一扫

位运算在LeetCode题目中的运用 ( C++ )

爱读书的歌者 2022-02-02 阅读 48
leetcodec++

文章目录

一、位运算符

运算符功能用法解释
&位与a&b相当于为二进制各位按位相乘,除1&1 = 1 其他均为0
|位或a|b两个操作数只要有一个为1则结果为1,即,除了0|0 = 0,其余均为1
^位异或a^b结果为二进制各位按位相乘,除1&1 = 1 其他均为0
<<左移a<<b相当于a × 2b
>>右移a>>b相当于a / 2b,并将小数部分舍去
~位求反~a整数a的二进制的每一位0变成1,1变成0

二、位运算应用

并集 :A | B
交集 :A & B
全集 :( 1 << n ) - 1
补集 :( ( 1 << n ) - 1 ) ^ A
A 是否是 B 的子集 :(A & B) == B
判断 n 是否是 2 的幂 :n & (n - 1) == 0
将 n 最低位的 1 变为 0 :n &= (n - 1)

三、例题

3.1 LeetCode 136. 只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]
输出: 1
示例 2:

输入: [4,1,2,1,2]
输出: 4

解题:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ans = 0;
        //根据交换律,例如1 ^ 2 ^ 1 = 1 ^ 1 ^ 2 = 0 ^ 2 = 2
        for(int i : nums) ans ^= i;
        return ans;
    }
};

3.2 LeetCode 191. 位1的个数

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
提示:

请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在上面的 示例 3 中,输入表示有符号整数 -3。

示例 1:

输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。

示例 2:

输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。

示例 3:

输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。

解题:

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int ans = 0;
        while(n != 0){
            //将n最低位的1变为0
            n &= (n - 1);
            ans++;
        }
        return ans;
    }
};

3.3 LeetCode 1763. 最长的美好子字符串

当一个字符串 s 包含的每一种字母的大写和小写形式 同时 出现在 s 中,就称这个字符串 s 是 美好 字符串。比方说,“abABB” 是美好字符串,因为 ‘A’ 和 ‘a’ 同时出现了,且 ‘B’ 和 ‘b’ 也同时出现了。然而,“abA” 不是美好字符串因为 ‘b’ 出现了,而 ‘B’ 没有出现。

给你一个字符串 s ,请你返回 s 最长的 美好子字符串 。如果有多个答案,请你返回 最早 出现的一个。如果不存在美好子字符串,请你返回一个空字符串。

示例 1:

输入:s = “YazaAay”
输出:“aAa”
解释:“aAa” 是一个美好字符串,因为这个子串中仅含一种字母,其小写形式 ‘a’ 和大写形式 ‘A’ 也同时出现了。
“aAa” 是最长的美好子字符串。

示例 2:

输入:s = “Bb”
输出:“Bb”
解释:“Bb” 是美好字符串,因为 ‘B’ 和 ‘b’ 都出现了。整个字符串也是原字符串的子字符串。

示例 3:

输入:s = “c”
输出:""
解释:没有美好子字符串。

示例 4:

输入:s = “dDzeE”
输出:“dD”
解释:“dD” 和 “eE” 都是最长美好子字符串。
由于有多个美好子字符串,返回 “dD” ,因为它出现得最早。

提示:

1 <= s.length <= 100
s 只包含大写和小写英文字母。

解题:

class Solution {
public:
    string longestNiceSubstring(string s) {
        int n = s.size();
        int pos = 0;
        int len = 0;
        for(int i = 0; i < n; i++){
            int lower = 0;
            int upper = 0;
            for(int j = i; j < n; j++){
                if(islower(s[j])){
                	//将小写字母用二进制进行标记
                    lower |= 1 << (s[j] - 'a');
                }else{
                    upper |= 1 << (s[j] - 'A');
                }
                //如果小写字母与大写字母的二进制标记相同,
                //则说明此子串满足没好子字符串的条件
                if(lower == upper && j - i + 1 > len){
                    pos = i;
                    len = j - i + 1;
                }
            }
        }
        return s.substr(pos, len);
    }
};
举报

相关推荐

0 条评论