优选算法2

五、位运算

常见位运算总结

&:有0就是0;

|:有1就是1

^:相同为0,相异就是1/无进位相加

给定一个数n,确定它的二进制表示中的第x位是0还是1:二进制中权值最小的是第0位,所以int整型是从第0位到第31位。于是n>>x &1就可以了

将一个数n的二进制表示的第x位修改成为1: (1<<x) | n

将一个数n的二进制表示的第x位修改成为0:(~(1<<x)) & n 

提取一个数n的二进制表示中最右侧的1:n&(-n),正数变成负数的二进制表示就是按位取法再加1。-n的本质是将最右侧的1的左边区域(不包括最右侧的1也就是当前位置)全部变成相反,其余的都不变。

干掉一个数n二进制表示中最右侧的1,也就是将这个1变成0:n&(n-1) ,n-1的本质是将最右侧的1右边的区域(包含1)全部变成相反。

异或:a^a=0;a^0=a;a^b^c=a^(b^c);交换律;采用无进位相加很容易证明 

 1.判断字符是否唯一


采用位图的思想:因为单独的一个整型变量就有32位比特位

优化点:鸽巢原理,也就是如果字符串的长度超过26,必定存在重复字符。

class Solution {
public:
    bool isUnique(string astr) 
    {
        //利用鸽巢原理进行优化
        if(astr.size()>26) return false;
        int bitmap=0;
        for(auto ch:astr)
        {
            //判断字符出现在哈希表中
            if((1<<(ch-'a')) & bitmap) return false;
            //将当前字符加入到位图中
            else bitmap+=(1<<(ch-'a'));//bitmap |= (1<<(ch-'a'))
        }
        return true;
    }
};

2.丢失的数字

class Solution {
public:
    int missingNumber(vector<int>& nums) 
    {
        int n=nums.size()+1;
        int result=0;
        for(auto ch:nums) result^=ch;
        for(int i=0;i<n;i++) result^=i;
        return result;
    }
};

3.两整数之和(巧妙)



利用异或的无进位相加,然后找到需要进位的地方。通过a&b可以找到需要进位的地方,因为只有1&1才能得到1,而这也是我们需要进位的地方。(a&b)<<1才是我们需要进位的位置。

class Solution {
public:
    int getSum(int a, int b) 
    {
        while(b)
        {
            int temp_a=a;
            a=temp_a^b;//先算出无进位相加的结果
            b=(temp_a&b)<<1;//算出进位
        }
        return a;
    }
};

4.只出现一次的数字


 

class Solution {
public:
    int singleNumber(vector<int>& nums) 
    {
        int ret=0;
        for(int i=0;i<32;i++)//依次去修改ret中的每一位
        {
            int sum=0;//统计nums中第i比特位出现1的次数
            for(auto ch:nums)
                if(ch & (1<<i)) sum++;
            if(sum%3) ret |= (1<<i);//修改ret的第i比特位
        }
        return ret;
    }
};

5.消失的两个数

  

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) 
    {
        vector<int> result;
        //将所有的数全部都异或到一起
        int tmp=0;
        int n=nums.size();
        for(auto ch:nums) tmp^=ch;
        for(int i=1;i<=n+2;i++) tmp^=i;
        //找到tmp中,比特位为1的那一位pos,在该比特位上a和b的比特值是不一样的。
        int pos;
        for(pos=0;pos<32;pos++) 
            if((tmp>>pos)&1) break;
        //根据pos位的不同,划分成为两类来异或
        int a=0,b=0;
        for(auto ch:nums)
        {
            if((ch>>pos)&1) a^=ch;
            else b^=ch;
        }
        for(int i=1;i<=n+2;i++)
        {
            if((i>>pos)&1) a^=i;
            else b^=i;
        }
        return {a,b};
    }
};

六、模拟算法

模拟算法就是依葫芦画瓢,思路比较简单,但是算法流程存在很多细节,将流程转换成为算法有比多要注意的细节。模拟题找优化一般都是通过找规律进行的。

6.替换所有的问号

class Solution {
public:
    string modifyString(string s) 
    {
        int n=s.size();
        //遍历字符串
        for(int i=0;i<n;i++)
        {
            //找到?字符
            if(s[i]=='?')
            {
                //遍历26个字母替换该字符
                for(char ch='a';ch<='z';ch++)
                {
                    //找到符合要求的字符,下面的if条件是关键
                    if((i==0 || ch!=s[i-1]) && (i==n-1 || ch!=s[i+1]))
                    {
                        s[i]=ch;
                        break;
                    }
                }
            }
        }
        return s;
    }
};

7.提莫攻击


 

class Solution {
public:
    int findPoisonedDuration(vector<int>& timeSeries, int duration) 
    {
        int result=0;
        for(int i=0;i<timeSeries.size()-1;i++)
        {
            if(timeSeries[i+1]-timeSeries[i]>=duration) result+=duration;
            else result+=(timeSeries[i+1]-timeSeries[i]);
        }
        return result+duration;
    }
};

8.Z字形变换


class Solution {
public:
    string convert(string s, int numRows) 
    {
        //处理边界情况
        if(numRows==1) return s;
        string result;
        int n=s.size();
        int d=numRows*2-2;//公差d
        //1.先处理第一行
        for(int i=0;i<n;i+=d)
        {
            result+=s[i];//
        }
        //2.处理中间行
        for(int k=1;k<numRows-1;k++)//枚举每一行
        {
            for(int i=k,j=d-k;i<n || j<n;i+=d,j+=d)//注意不要将i<n || j<n写成了i<n && j<n
            {
                if(i<n) result+=s[i];
                if(j<n) result+=s[j];
            }
        }
        //3.最后处理最后一行
        for(int i=numRows-1;i<n;i+=d)
        {
            result+=s[i];
        }
        return result;
    }
};

9.外观数列

class Solution {
public:
    string countAndSay(int n) 
    {
        string result="1";
        if(n==1) return result;
        for(int i=1;i<n;i++)//翻译n次
        {
            string tmp;
            int len=result.size();
            //采用双指针来进行翻译
            for(int left=0,right=0;right<len;)
            {
                while(right<len && result[left]==result[right]) right++;//当right=len-1的边界情况也可以正确处理
                tmp+=to_string(right-left);//to_string函数处理下标left和right的值不同的时候
                tmp+=result[left];
                left=right;
            }
            result=tmp;
        }
        return result;
    }
};

10.数青蛙


上述总结就是代码的逻辑非常重要

class Solution {
public:
    int minNumberOfFrogs(string croakOfFrogs) 
    {
        string t="croak";
        int n=t.size();
        vector<int> hash(n);//用数组来模拟哈希表
        unordered_map<char,int> index;//存储t字符串每个字符char以及对应的下标int
        for(int i=0;i<n;i++) index[t[i]]=i;
        //遍历字符串
        for(auto ch:croakOfFrogs)
        {
            //1、如果ch不在字符串t的范围内
            if(index.count(ch)==0) return -1;
            //2、如果字符ch不是c并且前面并没有匹配的字符
            if(ch!=t[0] && hash[index[ch]-1]<1) return -1;
            //3、正常运作
            if(ch==t[0] && hash[n-1]<1) hash[0]++;
            else if(ch==t[0] && hash[n-1]>=1) hash[0]++,hash[n-1]--;
            else hash[index[ch]]++,hash[index[ch]-1]--;
        }
        for(int i=0;i<n-1;i++) 
            if(hash[i]!=0) return -1;
        return hash[n-1];
    }
};

七、分治

分治就是分而治之,将一个大问题转换成为若干个相同或者相似的子问题,直到划分到子问题可以快速解决为止。

10.颜色分类(快排关键)


 

class Solution {
public:
    void sortColors(vector<int>& nums) 
    {
        int n=nums.size();
        int left=-1,right=n;
        for(int i=0;i<right;)//条件是i<right不是i<n,这是一个易错点。
        {
            if(nums[i]==0) swap(nums[++left],nums[i++]);
            else if(nums[i]==1) i++;
            else swap(nums[--right],nums[i]);
        }
    }
};

 11.排序数组 (快排)

class Solution {
public:
    int getrandom(vector<int>& nums,int left,int right)
    {
        int r=rand();
        return nums[r % (right-left+1) + left];
    }
    void sortArray_help(vector<int>& nums,int l,int r)
    {
        //定义递归出口
        if(l>=r) return;
        //随机方式选择基准元素
        int standar=getrandom(nums,l,r);
        int left=l-1;
        int right=r+1;
        //分成三块
        for(int i=l;i<right;)
        {
            if(nums[i]<standar) swap(nums[++left],nums[i++]);
            else if(nums[i]==standar) i++;
            else swap(nums[--right],nums[i]);  
        }
        sortArray_help(nums,l,left);
        sortArray_help(nums,right,r);
    }
    vector<int> sortArray(vector<int>& nums) 
    {
        srand(time(NULL));//种下一棵随机数种子
        sortArray_help(nums,0,nums.size()-1);
        return nums;
    }
};

12.数组中的第k个最大元素

class Solution {
public:
    int getrandom(vector<int>&nums,int left,int right)
    {
        int r=rand();
        return nums[r%(right-left+1)+left];
    }
    int qsort(vector<int>& nums,int l,int r,int k)
    {
        if(l==r) return nums[l];//容易遗漏的点
        //1、随机选择基准元素
        int standard=getrandom(nums,l,r);
        //2、根据基准元素将数组分成三块
        int left=l-1;
        int right=r+1;
        int i=l;
        while(i<right)
        {
            if(nums[i]<standard) swap(nums[++left],nums[i++]);
            else if(nums[i]==standard) i++;
            else swap(nums[--right],nums[i]);
        }
        //分情况讨论
        //下面的三个条件判断是关键
        if(r-right+1>=k) return qsort(nums,right,r,k);
        else if(r-left>=k) return standard;
        else return qsort(nums,l,left,k-r+left);
    }
    int findKthLargest(vector<int>& nums, int k) 
    {
        srand(time(NULL));
        return qsort(nums,0,nums.size()-1,k);
    }
};

13.最小k个数(未做)

14.归并排序(归并排序)

class Solution {
public:
    vector<int> tmp;//辅助数组用来排序
    void mergesort(vector<int>& nums,int left,int right)
    {
        if(right<=left) return;
        //1、选择中间点划分区间
        int mid=(left+right)/2; 
        //2、将左右区间排序
        int left1=left;
        int right1=mid;
        int left2=mid+1;
        int right2=right;
        mergesort(nums,left1,right1);
        mergesort(nums,left2,right2);
        int i=0;
        //3、合并两个有序数组
        while(left1<=right1 && left2<=right2) tmp[i++]=nums[left1]<=nums[left2]?nums[left1++]:nums[left2++];
        //4、处理没有遍历完的数组
        while(left1<=right1) tmp[i++]=nums[left1++];
        while(left2<=right2) tmp[i++]=nums[left2++];
        //5、还原
        for(int i=left;i<=right;i++) nums[i]=tmp[i-left];     
    }
    vector<int> sortArray(vector<int>& nums) 
    {
        tmp.resize(nums.size());
        mergesort(nums,0,nums.size()-1);
        return nums;
    }
};

15.交易逆序对的总数(未做)

class Solution {
public:
    int reversePairs_helper(vector<int>& nums,int left,int right)
    {
        if(left>=right) return 0;
        int ret=0;
        //1、找中间点,将数组分成两部分
        int mid=(left+right)>>1;
        //2.左边的个数+排序+右边的个数+排序
        ret +=reversePairs_helper(nums,left,mid);
        ret +=reversePairs_helper(nums,mid+1,right);
        //3.一左一右的个数
        int cur1=left,cur2=mid+1,i=0;
        vector<int> tmp(right-left+2);
        while(cur1<=mid && cur2<=right)
        {
            if(nums[cur1]<=nums[cur2]) tmp[i++]=nums[cur1++];
            else
            {
                ret+= mid-cur1+1;
                tmp[i++]=nums[cur2++];
            }
        }
        while(cur1<=mid) tmp[i++]=nums[cur1++];
        while(cur2<=right) tmp[i++]=nums[cur2++];
        for(int j=left;j<=right;j++)
            nums[j]=tmp[j-left];
        return ret;
      
    }
    
    int reversePairs(vector<int>& record) 
    {
        return reversePairs_helper(record,0,record.size()-1);
    }
};

16.計算右側小於當前元素的個數

class Solution {
    vector<int> ret;
    vector<int> index;//记录nums当前元素的下标、
    int tmpNums[500010];
    int tmpIndex[500010];
public:
    vector<int> countSmaller(vector<int>& nums) {
        int n=nums.size();
        ret.resize(n);
        index.resize(n);
        for(int i=0;i<n;i++)
            index[i]=i;
        mergesort(nums,0,nums.size()-1);
        return ret;
    }
    void mergesort(vector<int>& nums,int left,int right)  {
        if(left>=right) return;
        int mid=(left+right)>>1;
        mergesort(nums,left,mid);
        mergesort(nums,mid+1,right);
        int cur1=left,cur2=mid+1,i=0;
        while(cur1<=mid && cur2<=right)
        {
            if(nums[cur1]>nums[cur2])
            {
                tmpNums[i]=nums[cur1];
                ret[index[cur1]]+=right-cur2+1;
                tmpIndex[i]=index[cur1];
                i++;
                cur1++;
            }
            else
            {
                tmpNums[i]=nums[cur2];
                tmpIndex[i]=index[cur2];
                i++;
                cur2++;
            }
        }

        while(cur1<=mid)
        {
            tmpNums[i]=nums[cur1];
            tmpIndex[i]=index[cur1];
            i++;
            cur1++;
        }
        while(cur2<=right)
        {
            tmpNums[i]=nums[cur2];
            tmpIndex[i]=index[cur2];
            i++;
            cur2++;
        }
        for(int j=left;j<=right;j++)
        {
            nums[j]=tmpNums[j-left];
            index[j]=tmpIndex[j-left];
        }

       
    }
};

17.翻转对

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/756079.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

os实训课程模拟考试(选择题复习)

目录 一、操作系统的基本功能和设计目标 &#xff08;1&#xff09;基础知识 &#xff08;2&#xff09;题目与答案 1、操作系统是一组 B &#xff08;单选&#xff09; 2、以下哪项不是操作系统关心的主要问题&#xff1f;D &#xff08;单选&#xff09; 3、下列关于…

基于Ansys workbench进行发动机风扇非定常流固耦合计算

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&…

MFC扩展库BCGControlBar Pro v35.0新版亮点 - 工具栏、菜单全新升级

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中&#xff0c;并为您节省数百个开发和调试时间。 BCGControlBar专业版 v35.0已全新发布了&#xff0c;这个版本改进类Visual Studio 2022的视觉主题、增强对多个…

pytest中的极其重要固件(request)的理解

pytest 是一个非常流行的Python测试框架&#xff0c;它为开发人员提供了丰寴的测试工具和功能。 在pytest中&#xff0c;固件&#xff08;fixture&#xff09;是一种非常核心的概念&#xff0c;用于设置测试前的预条件&#xff0c;清理测试后的环境&#xff0c;或者提供测试过…

vxeTable反转表格

文章目录 前言 前言 如果遇到列为动态值&#xff0c;行相对固定的情况&#xff0c;这种时候就需要用到行列反转&#xff0c;这里我以vxeTable表格为例。 直接上代码 <vxe-gridref"tableRefRight":auto-resize"true":columns"dataColumn":dat…

springboot中使用springboot cache

前言&#xff1a;SpringBoot中使用Cache缓存可以提高对缓存的开发效率 此图片是SpringBootCache常用注解 Springboot Cache中常用注解 第一步&#xff1a;引入依赖 <!--缓存--><dependency><groupId>org.springframework.boot</groupId><artifactId…

【ai】trition:tritonclient yolov4:ubuntu18.04部署python client成功

X:\05_trition_yolov4_clients\01-python server代码在115上,client本想在windows上, 【ai】trition:tritonclient.utils.shared_memory 仅支持linux 看起来要分离。 【ai】tx2 nx:ubuntu18.04 yolov4-triton-tensorrt 成功部署server 运行 client代码远程部署在ubuntu18.0…

分布式锁及其实现与应用场景

分布式锁及其实现与应用场景 分布式锁是一种用于在分布式系统中协调多个进程或线程对共享资源进行访问的机制。它的主要目的是确保在同一时间只有一个进程或线程可以访问特定资源&#xff0c;从而避免数据竞争和不一致问题。分布式锁通常用于集群环境中&#xff0c;例如微服务…

二次封装 el-dialog 实现 全屏和最小化 功能

效果 封装后的组件 <template><el-dialog v-model"dialogVisible" :show-close"false" :fullscreen"fullscreen" draggable overflow><template #header"{ close }"><div><span style"font-weight: b…

Python operator模块这么用,效率杠杠的!

目录 1、基础操作符应用 🐍 1.1 加载operator模块 1.2 使用itemgetter进行排序 1.3 attrgetter与方法调用 2、高级功能探索 🔍 2.1 methodcaller的妙用 2.2 操作符重载与定制 3、结合lambda表达式 ✨ 3.1 lambda与operator模块协同工作 3.2 实战案例分析 4、结合…

nginx架构基本数据结构配置模块请求详解

nginx源码的目录结构&#xff1a; . ├── auto 自动检测系统环境以及编译相关的脚本 │ ├── cc 关于编译器相关的编译选项的检测脚本 │ ├── lib nginx编译所需要的一些库的检测脚本 │ ├── os 与平台相关的一些系统参…

【sqlmap命令学习及测试dvwa_SQL_Injection】

文章目录 1.sqlmap命令及 不同级别探索 能否注入命令option1.1 low等级1.2 Medium等级1. 3 High等级 2. 注入流程2.1 数据库2.2 指定数据库表名2.3 指定表的 字段名2.4 内容2.5 当前用户信息2.6 用户密码2.7 其他 1.sqlmap命令及 不同级别探索 能否注入 命令option sqlmap -u…

石家庄高校大学智能制造实验室数字孪生可视化系统平台项目验收

智能制造作为未来制造业的发展方向&#xff0c;已成为各国竞相发展的重点领域。石家庄高校大学智能制造实验室积极响应国家发展战略&#xff0c;结合自身优势&#xff0c;决定引进数字孪生技术&#xff0c;构建一个集教学、科研、生产于一体的可视化系统平台。 数字孪生可视化…

influxdb时序数据库使用

influxdb时序数据库使用 1.1.免费无云influx申请1.2.Telegraf安装1.3.influxdb安装mac安装Redhat && Centos安装docker安装Kubernetes安装windows安装 1.4.influx CLI 安装1.5.influx命令行界面1.5.influx配置项权限认证配置管理 API 令牌 InfluxDB 是一个开源分布式时…

kali Linux基本命令(超全)_kali linux命令

一、系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件- (SMBIOS / DMI) hdparm -i /dev/hda 罗列一个磁盘的架构特性 hdparm -tT /dev/sda 在磁盘上执行测试性读取操作 cat /proc/cpu…

【从0实现React18】 (六) 完成commit提交流程并初步实现react-dom包,完成首屏渲染测试

前面&#xff0c;我们提到 React 更新流程有四个阶段&#xff1a; 触发更新&#xff08;Update Trigger&#xff09;调度阶段&#xff08;Schedule Phase&#xff09;协调阶段&#xff08;Reconciliation Phase&#xff09;提交阶段&#xff08;Commit Phase&#xff09; 之前…

安防监控视频平台LntonAIServer视频监控管理平台裸土检测算法技术核心和应用场景

LntonAIServer裸土检测算法是一种基于人工智能技术的创新解决方案&#xff0c;旨在实现对裸土地表的自动识别。以下是对该算法的详细分析&#xff1a; 技术基础&#xff1a; 1、该算法利用深度学习和计算机视觉技术&#xff0c;通过捕捉视频或图像中的关键信息&#xff0c;如…

【ES】--Elasticsearch的翻页详解

目录 一、前言二、from+size浅分页1、from+size导致深度分页问题三、scroll深分页1、scroll原理2、scroll可以返回总计数量四、search_after深分页1、search_after避免深度分页问题一、前言 ES的分页常见的主要有三种方式:from+size浅分页、scroll深分页、search_after分页。…

IT运维问题分析报告编写经验模版

IT运维问题分析报告编写经验&模版 为提高IT运维用户服务感知满意度&#xff0c;提高运维工作效率&#xff0c;完善运维基础设施建设&#xff0c;现对IT运维工作中存在的紧迫性问题进行分析总结&#xff0c;报告如下&#xff1a; 本文参考资料。专栏地址&#xff08;50运维…

期末考试结束,成绩如何快速发布?

随着期末考试的落幕&#xff0c;老师们又迎来了一项繁琐的任务将成绩单私信给学生家长。这项工作耗时耗力&#xff0c;而且极易出错&#xff0c;期末老师的工作已经足够繁重还要私发成绩&#xff0c;简直是雪上加霜。 好消息是&#xff0c;现在有了易查分小程序&#xff0c;只需…