优选算法——位运算


👇作者其它专栏

《数据结构与算法》《算法》《C++起始之路》


1.前要知识

《位操作符的妙用》

2.相关题解

2.1判定字符是否唯一

算法思路:

利用【位图】的思想,每一个【比特位】代表一个【字符】,一个int类型的变量的32位足够表示所有的小写字母。比特位里若为0,表示这个字符没有出现过;若为1,表示该字符出现过。

可以用一个【整数】来充当【哈希表】。

class Solution { public: bool isUnique(string astr) { //利用鸽巢原理优化 if(astr.size()>26) return false; int bitmap=0; for(auto i:astr){ int e=i-'a'; //先判断字符是否出现过 if(((bitmap>>e)&1)==1) return false; //把当前字符加入到位图中 bitmap|=1<<e; } return true; } };

2.2消失的数字

算法思路:

设数组的大小为n,则之前的数组就是[0,n],数组中是[0,n]中缺失一个数形成的序列。若,我们把数组中的所有数,以及[0,n]中的所有数全部【异或】在一起,那么根据【异或】运算的【消消乐】规则,最终的异或结果就是缺失的数字。

//1.哈希 2.高斯定理 3.位运算 4.排序+(暴力或二分) class Solution { public: int missingNumber(vector<int>& nums) { int ret=0; for(auto i:nums) ret^=i; for(int i=0;i<=nums.size();i++) ret^=i; return ret; } };

2.3两整数之和

算法思路:

●异或^运算本质是【无进位加法】;

●按位与&操作能够得到【进位】;

●然后一直循环进行,直到【进位】变成0为止

class Solution { public: int getSum(int a, int b) { while(b){ int x=a^b;//无进位相加的结果 //排除-1的情况 unsigned int carry=(a&b)<<1;//进位 a=x; b=carry; } return a; } };

2.4只出现一次的数字 II

算法思路:

设要找的数为ret。由于整个数组中,需要找的元素只出现了【一次】,其余的数都出现了【三次】,因此我们可以根据所有数的【某一个比特位】的总和%3的结果,快速定位到ret的【一个比特位】上的值是0还是1。

这样,我们通过ret的每一位比特位上的值,就可以将ret给还原出来。

class Solution { public: int singleNumber(vector<int>& nums) { int ret=0; for(int i=0;i<32;i++){//依次修改ret中的每一位 int sum=0; for(auto x:nums)//计算nums中所有第i位的和 if(x&(1<<i)) sum++; sum%=3; if(sum&1) ret|=1<<i; } return ret; } };

2.5只出现一次的数字 III

算法思路:

1.将所有数异或在一起,由于只有两个数出现一次,其余都出现两次。所以最后的结果为a^b

2.a和b不相等,因此a和b的二进制一定有至少一位不相同,

class Solution { public: vector<int> singleNumber(vector<int>& nums) { //1.将所有的数异或在一起 int tmp=0; for(auto x:nums) tmp^=x; //2.找出a,b中比特位不同的那一位 int diff=0; while(1){ if(((tmp>>diff)&1)==1) break; else diff++; } //3.根据diff位的不同,将所有数划分成两类 int a=0,b=0; for(auto x:nums){ if((1&(x>>diff))==1) b^=x; else a^=x; } return {a,b}; } };

2.6消失的两个数字

本题就是 2.2消失的数字+2.5只出现一次的数字 III组合起来的题。

现将数组中的数和[1,n+2]区间内的所有数【异或】在一起,问题就变成了:有两个数出现了【一次】,其余所有的数出现了【两次】。进而变成了2.5只出现一次的数字 III这道题。

class Solution { public: vector<int> missingTwo(vector<int>& nums) { //1.将所有的数异或在一起 int tmp=0; for(auto x:nums) tmp^=x; for(int i=1;i<=nums.size()+2;i++) tmp^=i; //2.找出a,b中比特位不同的那一位 int diff=0; while(1){ if(((tmp>>diff)&1)==1) break; else diff++; } //3.根据diff位的不同,将所有数划分成两类 int a=0,b=0; for(auto x:nums){ if((1&(x>>diff))==1) b^=x; else a^=x; } for(int i=1;i<=nums.size()+2;i++){ if((1&(i>>diff))==1) b^=i; else a^=i; } return {a,b}; } };

Read more

【数据结构】感受递归暴力美学:链式二叉树全方位剖析(附源码)

【数据结构】感受递归暴力美学:链式二叉树全方位剖析(附源码)

🔥 @晨非辰Tong: 个人主页 👀专栏:《C语言》、《数据结构与算法入门指南》 💪学习阶段:C语言、数据结构与算法初学者 ⏳“人理解迭代,神理解递归。” 文章目录 * **引言** * 一、介绍链式二叉树 * 1.1 概念 * 1.2 基本结构(结构上的递归性) * 二、遍历接口实现(操作上的递归性) * 2.1 前序遍历(根左右) * 1. 概念 * 2. 代码 * 2.2 中序遍历(左根右) * 1. 概念 * 2.代码 * 2.3 后序遍历 * 1. 概念 * 2. 代码 * 三、其余接口实现(操作上的递归性)

By Ne0inhk

优选算法——二分查找

👇作者其它专栏 《数据结构与算法》《算法》《C++起始之路》 二分查找相关题解 1.二分查找 算法思路: a.定义left,right指针,分别指向数组的左右区间。 b.找到待查找区间的中间点mid,找到后分三种情况讨论:         i.arr[mid]==target说明正好找到,返回mid的值;         ii.arr[mid]>target说明[mid,right]这段区间都是大于target的,因此舍去右边区间,在左边[left,mid-1]的区间继续查找,即让right=mid-1,然后重复b过程;         iii.arr[mid]<target说明[left,mid]这段区间的值都是小于target的,因此舍去左边区间,在右边区间[mid+1,right]

By Ne0inhk
【初阶数据结构08】——树的基本概念与堆的基本功能实现

【初阶数据结构08】——树的基本概念与堆的基本功能实现

文章目录 前言 一、树的概念 1.1 树的定义 1.2 树的相关术语 1.3 树的表示 1.4 树在实际中的应用 二、二叉树概念及结构 2.1 二叉树的定义 2.2 现实中的二叉树 2.3 特殊的二叉树 2.4 二叉树的性质 2.5 二叉树的存储结构 1. 顺序存储 2. 链式存储 三、堆的概念与结构 3.1 堆的定义 3.2 堆的存储结构 四、堆的基本功能实现 4.1 辅助函数:

By Ne0inhk
Flutter 三方库 crypto 的鸿蒙化适配指南 - 实现具备工业级哈希算法与消息摘要计算的安全底座、支持端侧数据校验与数字签名实战

Flutter 三方库 crypto 的鸿蒙化适配指南 - 实现具备工业级哈希算法与消息摘要计算的安全底座、支持端侧数据校验与数字签名实战

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 crypto 的鸿蒙化适配指南 - 实现具备工业级哈希算法与消息摘要计算的安全底座、支持端侧数据校验与数字签名实战 前言 在进行 Flutter for OpenHarmony 开发时,确保数据的一致性与安全性是业务上线的先决条件。无论是对用户密码进行加盐哈希存储、验证下载文件的完整性,还是为分布式信令生成 API 签名,都离不开严谨的加密算法支持。crypto 是 Dart 官方生态中用于处理哈希与摘要的核心工具库。本文将探讨如何在鸿蒙端构建极致、稳健的加密算法基石。 一、原直观解析 / 概念介绍 1.1 基础原理 该库提供了一系列纯 Dart 实现的一致性哈希算法(Hash Algorithims)。它通过将任意长度的输入映射为固定长度的二进制摘要(Digest)。支持流式处理(Chunked processing),即允许在读取大文件时分批次泵送数据。在鸿蒙端。它是“

By Ne0inhk