LeetCode刷题--位运算

目录

判定字符是否唯一

题目解析

算法原理

解法一 :用int hash[26]哈希表去遍历整个字符串,如果谋个字符出现的次数 > 1次,那么返回true,否则返回false

时间复杂度:O(N) 遍历一遍数组

空间复杂度:O(N) 开了一个哈希表

解法二 :用位图的思想,因为字符不超过32个

位图的下标是0到31

0表示字符未出现过,1表示这个字符已经出现过一次了

鸽巢原理的优化:

只要字符的长度超过了26表示一定出现了重复字符

代码

cpp 复制代码
class Solution 
{
public:
    bool isUnique(string astr) 
    {
     // 哈希表
    //   int hash[128] = {0};
    //   for(int i = 0;i < astr.size();++i)
    //   hash[astr[i]]++;
    //   for(int i = 0;i < astr.size();++i)
    //   {
    //       if(hash[astr[i]] != 1) return false;
    //   }
    //   return true;
      // 位图 + 优化(鸽巢原理)
        int n = astr.size();
        if(n > 26) return false;// 优化
        // 位图
        int bitMap = 0;
        for(auto ch : astr)
        {
            int i = ch - 'a';
            // 判断字符是否重复
            if((bitMap >> i)&1) return false;
            // 否则将字符加入到位图中
            bitMap |= (1 << i);
        }
        return true;
    }
};

丢失的数字

题目解析

算法原理

代码

cpp 复制代码
class Solution 
{
public:
    int missingNumber(vector<int>& nums) 
    {
        // 位运算
        // 时间O(N) 空间O(1)
        int ret = 0; 
        for(auto x : nums) ret ^= x;
        for(int i = 0;i <= nums.size();++i) 
        ret ^= i;
        return ret;

        int sum = 0;
        vector<int> v(nums.size()+1);
        for(int i = 0;i < nums.size() + 1;++i)
        {
            v[i] = i;
            sum ^= v[i];
        }
        for(int i = 0;i < nums.size();++i)
        {
            sum ^= nums[i];
        }
        return sum;

        // 哈希表
        // 时间O(N) 空间O(N)
        int n = nums.size();
        int hash[10000] = {0};
        for(int i = 0;i < n;++i) hash[nums[i]]++;
        for(int i = 0;i <= n;++i) 
        {
            if(hash[i] == 0) return i;
        } 
        return -1;

        // 高斯求和
        // 时间O(N) 空间O(1)
        int sum = 0;
        int n = nums.size();
        // 全部的和
        int k = (0+n)*(n+1) / 2;
        for (int i = 0; i < n; ++i) 
        sum += nums[i];// 数组中的和
       
        return k - sum;// 缺失的数
    }
};

两整数之和

题目解析

算法原理

a^b表示无进位加法
a&b,表示保留进位
(a&b)<< 1,表示进位
a^b 再和(a&b) << 1 异或(无进位相加后再循环上面的步骤直到进位为0就是答案)

代码

cpp 复制代码
class Solution 
{
public:
    // <*>
    int getSum(int a, int b) 
    {
        // int sum = 0;
        // while(b != 0)
        // {
        //     int tmp = a & b;
        //     a = a ^ b;
        //     b = tmp << 1;
        // }
        // return a;
        while(b != 0)
        {
            int x = a ^ b;
            unsigned int tmp =(unsigned int)(a & b) << 1;
            a = x;
            b = tmp;
        }
        return a;
    }
};

只出现一次的数字 II

题目解析

算法原理

把所有数第0位的比特位的值相加然后%3,有三个相同的数,得到的最终结果是唯一的那个数的比特位

代码

cpp 复制代码
class Solution 
{
public:
    // <*>
    int singleNumber(vector<int>& nums) 
    {
       int ret = 0;
       for(int i = 0;i < 32;++i)// 0 ~ 31
       {
         int sum = 0;// 记录所有数当前位,比特位的和
         for(auto x : nums)
         if((x >> i)&1 == 1) sum++;
         sum %= 3;// 得到唯一出现数当前比特位的值1或0
         if(sum == 1) ret |= (1 << i); // 当前位,比特位放入结果中
       }
       return ret;
    }
};

消失的两个数字

题目解析

算法原理

不是缺失了两个数字吗,那么全部数异或起来就是a^b的值,tmp = a ^ b,tmp肯定不等于0,那么肯定他们两有一个比特位上的数字是不同的,0或1,就找是0还是1就可以区分它们了

代码

cpp 复制代码
class Solution 
{
public:
    vector<int> missingTwo(vector<int>& nums) 
    {
        // int n = nums.size();
        // vector<int> ret;
        // int hash[30001] = {0};
        // for(int i = 0;i < n;++i) 
        // hash[nums[i]]++;
        // for(int i = 1;i <= n+2;++i)
        // if(hash[i] != 1) ret.push_back(i);
        //  return ret;

        // 1. 得到缺失的两个数异或的值
        int tmp = 0;
        for(auto x:nums) tmp ^= x;
        for(int i = 1;i <= nums.size() + 2;++i) tmp ^= i;
        
        // 2. 找出缺失的位置tmp != 0,必然至少一个数的位置上是0^1
        int k = 0;
        while(1)
        {
            if(((tmp >> k)&1)== 1) break;
            else k++; 
        }

        // 3. 根据比特位上是0还是1可以分开两个数
        int a = 0,b = 0;
        for(auto x : nums)
        {
            if(((x >> k)&1) == 1) a ^= x;
            else b ^= x;
        }
        for(int i = 1;i <= nums.size() + 2;++i)
        {
            if(((i >> k)&1) == 1) a ^= i;
            else b ^= i;
        }
        return {a,b};
    }
};

恭喜你看到这里了,那就祝你题题AC ! ! !

相关推荐
兴科Sinco14 分钟前
[leetcode 1]给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数[力扣]
python·算法·leetcode
薛定谔的算法24 分钟前
JavaScript单链表实现详解:从基础到实践
数据结构·算法·leetcode
元亓亓亓4 小时前
LeetCode热题100--230. 二叉搜索树中第 K 小的元素--中等
算法·leetcode·职场和发展
草莓熊Lotso4 小时前
《算法闯关指南:优选算法-双指针》--01移动零,02复写零
c语言·c++·经验分享·算法·leetcode
小欣加油12 小时前
leetcode 面试题01.02判定是否互为字符重排
数据结构·c++·算法·leetcode·职场和发展
3Cloudream12 小时前
LeetCode 003. 无重复字符的最长子串 - 滑动窗口与哈希表详解
算法·leetcode·字符串·双指针·滑动窗口·哈希表·中等
林木辛17 小时前
LeetCode热题 42.接雨水
算法·leetcode
黑菜钟19 小时前
代码随想录第七天|● 454.四数相加II ● 383. 赎金信 ● 15. 三数之和 18.四数之和
c++·算法·leetcode
pzx_00120 小时前
【LeetCode】14. 最长公共前缀
算法·leetcode·职场和发展
songx_9921 小时前
leetcode10(跳跃游戏 II)
数据结构·算法·leetcode