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

相关推荐
未知陨落36 分钟前
leetcode题目(1)
c++·leetcode
m0_694938018 小时前
Leetcode打卡:字符串及其反转中是否存在同一子字符串
linux·服务器·leetcode
chenziang18 小时前
leetcode hot 100 二叉搜索
数据结构·算法·leetcode
茶猫_13 小时前
力扣面试题 - 40 迷路的机器人 C语言解法
c语言·数据结构·算法·leetcode·机器人·深度优先
Abelard_14 小时前
LeetCode--347.前k个高频元素(使用优先队列解决)
java·算法·leetcode
Tisfy15 小时前
LeetCode 3218.切蛋糕的最小总开销 I:记忆化搜索(深度优先搜索DFS)
算法·leetcode·深度优先·题解·记忆化搜索
想要AC的sjh16 小时前
【Leetcode】3159. 查询数组中元素的出现位置
数据结构·算法·leetcode
虽千万人 吾往矣16 小时前
golang LeetCode 热题 100(技巧)-更新中
算法·leetcode·职场和发展
南宫生16 小时前
力扣-数据结构-4【算法学习day.75】
java·数据结构·学习·算法·leetcode
fks14316 小时前
leetcode 354. 俄罗斯套娃信封问题
leetcode