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 ! ! !

相关推荐
wsxqaz2 小时前
浏览器原生控件上传PDF导致hash值不同
算法·pdf·哈希算法
hn小菜鸡10 小时前
LeetCode 377.组合总和IV
数据结构·算法·leetcode
亮亮爱刷题10 天前
飞往大厂梦之算法提升-7
数据结构·算法·leetcode·动态规划
双叶83610 天前
(C语言)Map数组的实现(数据结构)(链表)(指针)
c语言·数据结构·c++·算法·链表·哈希算法
安全系统学习10 天前
【网络安全】DNS 域原理、危害及防御
算法·安全·web安全·网络安全·哈希算法
zmuy10 天前
124. 二叉树中的最大路径和
数据结构·算法·leetcode
chao_78910 天前
滑动窗口题解——找到字符串中所有字母异位词【LeetCode】
数据结构·算法·leetcode
Alfred king10 天前
面试150跳跃游戏
python·leetcode·游戏·贪心算法
呆呆的小鳄鱼10 天前
leetcode:746. 使用最小花费爬楼梯
算法·leetcode·职场和发展
英雄哪里出来10 天前
《哈希表》K倍区间(解题报告)
数据结构·算法·散列表·哈希表·解题报告