首页 > 编程语言 >初识算法 · 位运算(2)

初识算法 · 位运算(2)

时间:2024-11-13 21:43:44浏览次数:3  
标签:题目 运算 nums int 异或 ret 算法 初识 数字

目录

前言:

判定字符是否唯一

丢失的数字

比特位计数

只出现一次的数字III


前言:

​本文的主题是位运算,通过四道题目讲解,一道是判断字符是否唯一,一道是只出现一次的数字III,一道是比特位计数,一道是丢失的数字。
链接分别为:

338. 比特位计数 - 力扣(LeetCode) 面试题 01.01. 判定字符是否唯一 - 力扣(LeetCode)

260. 只出现一次的数字 III - 力扣(LeetCode) 268. 丢失的数字 - 力扣(LeetCode)

因为这些题目都是比较简单的,所以一一揉在一起介绍。

那么,话不多说,直接进行主题咯。


判定字符是否唯一

这道题目是作为面试题目出现的,作为一道面试题目,它有很多解法,比如我们可以使用哈希映射,使用map 使用set,使用函数count就可以判断是否出现了两次,也可以使用数组,遍历一遍,看哪个下标对应的值是2就返回false即可,解法是非常非常多的,说白了,这道题目就是让我们判读这堆“数字”里面是否有重复的数字。

那么前两个方法,多多少少都用到了额外的数据结构,额外的空间,相对来说还是没有那么好,毕竟空间还是大了一点,我们不妨利用位图的思想,一个Int就可以搞定,遍历到的时候,将位图对应的位置置为1,再次如果判断到了,直接返回false即可。

当然了,这道题目可以使用鸽巢原理进行优化,一共才26个英文字符,如果字符串的长度超过了26,直接返回false即可。

以上是题目解析 + 算法原理,以下是原理编写:

class Solution 
{
public:
    bool isUnique(string astr) 
    {
        int bitmap = 0;
        for(auto e : astr)
        {
            int x = e - 'a';
            if(((bitmap >> x) & 1) == 1) return false;
            else bitmap |= (1 << x);
        }    
        return true;
    }
};

丢失的数字

题目十分简单,我们现在应该思考的是,我们可以用多少种解法,这道题目无非就是让我们从一个连续的数集里面找到缺失的数字就可以了。“那这道题不就是缺失的数字吗”

第一种解法,高斯求和,因为数字肯定是从0开始到n的,所以我们可以将0到n这段区间的所有的数字加起来,最后减去给我们的这段区间的和即可。时间复杂度为O(N) 空间复杂度为O(1)

第二种解法,哈希映射,我们就开一个n + 1的数组,遍历数组,对应下标+1,看谁为2即可。时间复杂度为O(N) 空间复杂度为O(N),相对来说就不是那么好了。

第三种解法,遍历数组看i + 1是否为前一个数 + 1即可。

第四种解法,异或的运算律,数组的下标和数异或,看谁空出来了就可以了。

class Solution {
public:
    int missingNumber(vector<int>& nums) 
    {        
        sort(nums.begin(),nums.end());
        if(nums[0] != 0) return 0;
        int i = 0;
        for(i = 0; i < nums.size() - 1; i++)
        {
            if(nums[i] != (nums[i + 1] - 1)) return nums[i] + 1;
        }    
        return nums[i] + 1;
    }
};

对于第三种解法是比较差劲的,因为还是注意许多细节问题,比如需要先排序,还要判断1 2的这种情况,那么对于异或来说,就很不错了:

class Solution 
{
public:
    int missingNumber(vector<int>& nums) 
    {
        int ret = 0;
        for(auto e : nums) ret ^= e;
        for(int i = 1;i <= nums.size();i++)
            ret ^= i;

        return ret;
    }
};

比特位计数

题目的要求是计算从0到n的所有的数中的二进制表示中1的个数,将个数插入到顺序表,然后返回就可以了。

那这道题不就是多次计算比特位中1的个数吗?我们甚至可以直接复用上篇那道题目的代码:

class Solution 
{
public:
    int countone(int n)
    {
        int x = 0;
        while(n)
        {
            n &= (n - 1);
            x++;
        }
        return x;
    }
    vector<int> countBits(int n) 
    {
        vector<int> v;
        for(int i = 0; i <= n; i++)
        {
            v.push_back(countone(i));
        }
        return v;
    }
};

只出现一次的数字III

这道题目无非就是找单身狗plus版本而已,就是缺失的数字嘛对吧!

我们需要找到两个数,那么异或整个数组肯定是少不了的,异或了之后,剩余的是两个数的异或结果,那么我们如何分离出来呢?

我们可以结合基本题目 :提取最低位的1,提取出来之后,两个只出现一次的数字在该位上一定是不同的,因为异或出来结果是1,其他的数也异或掉了,所以一定是一个为1,一个为0。

那么我们利用这个特点,将数组中的每个数组和最低位的数字一&运算一下,就可以得到结果了,因为没有要求顺序,所以我们可以直接输出。

class Solution 
{
public:
    vector<int> singleNumber(vector<int>& nums) 
    {
        //先将整个数组异或
        int ret = 0;
        for(auto e : nums) ret ^= e;
        //获取最低位的1->实际上是分组
        // int low_bit = ret & -ret;
         int low_bit = (ret == INT_MIN ? ret : ret & (-ret));
        //开始分组
        int ans1 = 0, ans2 = 0;
        for(auto e : nums)
        {
            if(e & low_bit) ans1 ^= e;
            else ans2 ^= e;
        }
        return { ans1, ans2 };
    }
};

以上就是位运算的多个题目解析。


感谢阅读!

标签:题目,运算,nums,int,异或,ret,算法,初识,数字
From: https://blog.csdn.net/2301_79697943/article/details/143751400

相关文章

  • 处理回文串的两种方法:动态规划 | 马拉车(Manacher)算法
    一.前言对于回文串的处理方法有很多,还有中心扩展、哈希等方法。这里只是介绍两种我觉得有用的方法。这里的两种方法不针对的某一种特定题目,他们是一种解题思路,这两个算法像一个工具一样,在有需要的时候使用。二.一维动态规划首先介绍一下这个算法的作用,我们预处理出一个一维d......
  • 数据类型和运算符
    数据类型动态类型编程语言运行时判断静态类型的编程语言:Go、C、在开发的时候,就需要给一些定义的变量赋值空间大小。C需要自己去开辟这个空间数据类型:每种在Go语言中出现的基本数据类型,会有一个默认的空间大小。1、布尔类型数据布尔型的值只可以是常量true或者......
  • 从文法到解析器的所有算法
    从文法到解析器的所有算法最近完成了替代Lex+YACC的自动生成词法分析器+语法分析器的项目,暂且命名为YAC。想拥有自己的解析器的小伙伴可以将文法给我,送解析器。下面是一个支持加减乘除和括号的四则运算的文法:Calc.stsyntax{Additive:Additive'+'Multiplicative......
  • jvm 垃圾回收算法
    如何实现回收的(核心思想):1.找到内存中存活的对象(与GCRoot相关联)2.释放不再存活对象的内存,使得程序能再次利用这部分空间---------------------------------------------------------------------------------垃圾回收算法的分类: -------- ---------------------------......
  • 【Unity人群寻路插件】CrowdPath Pathfinding 高效的路径规划算法来模拟群体寻路行为,
    CrowdPathPathfinding是一款专为Unity设计的路径寻找插件,主要用于处理复杂的人群导航问题,特别适合需要大规模虚拟人物群体移动的游戏或应用。它通过高效的路径规划算法来模拟群体行为,如避开障碍、避免拥挤、相互避让等。主要特点:高效的人群路径寻找:插件能够在复杂环境......
  • 一、机器学习算法与实践_07支持向量机与集成学习算法笔记
    1支持向量机1.1定义SVM(SupportVectorMachine,即:支持向量机)是一种监督学习算法,主要用于分类问题,但也可用于回归分析(称为支持向量回归,SupportVectorRegression,简称SVR)1.2核心思想最大间隔原则:SVM试图找到一个超平面(在二维空间中是一条直线,在三维空间中是一个平面,在更......
  • canny 算法 python实现, 双边滤波--自适应阈值改进--形态学操作
    #-*-coding:utf-8-*-importnumpyasnpimportcv2importosimportcsv#高斯滤波defsmooth(image,sigma=1.4,length=5):#Computegaussianfilterk=length//2gaussian=np.zeros([length,length])foriinrange(length):for......
  • 弹性伸缩:高可用架构利器(架构+算法+思维)
    弹性伸缩:高可用架构利器(架构+算法+思维) 1介绍云计算资源弹性伸缩是一种根据业务需求动态调整计算资源规模的技术。它可以根据系统的性能指标(如CPU使用率、内存占用率、磁盘IO、网卡读写率、请求响应时间等)或者预定义的规则(如时间周期、业务事件等),自动增加或减少计算资源的......
  • ECMAScript 安全赋值运算符 (?=) 提案介绍及其 Polyfill
    本文介绍最新的ECMAScript安全赋值运算符提案以及相应的替代实现前言我们经常会跟try/catch打交道,但如果你写过Go或者Rust就会发现在这两种语言中是没有try/catch的,那么这些语言怎么进行错误捕获呢Go:Errorhandlingf,err:=os.Open("filename.ext")iferr......
  • 算法复杂度
    递归复杂度接前面常见初等函数的变化曲线T(n)=......