算法基础-->概率组合
来源:互联网 发布:java 定时 编辑:程序博客网 时间:2024/06/07 18:58
本篇博文将总结数学相关的内容,涉及概率组合的一些算法,比较简单。
求1的个数
问题描述
给定一个
问题分析
方法一
显然:可以通过不断的将整数
int OneNumber(int n){ int c = 0; while (n!=0) { c += (n & 1);//n末尾最后一位不断和1作与 n >>= 1;//n=n>>1,n右移一位 } return c;}
方法二
每次将
int OneNumber2(int n){ int c = 0; while (n!=0) { n = n&(n - 1);//将n的最后一个“1”清零 c++;//每清除一个1,c就加一 } return c;}
方法三:分治
假定能够求出
为了节省空间,用一个
- 高
16 位记录a ,低16 位记录b ; (0xFFFF0000&N) 筛选得到a ;(0x0000FFFF&N) 筛选得到b ;(0xFFFF0000&N)+(0x0000FFFF&N)>>16
如何得到高
- 分治往往伴随着递归
递归过程:
如果二进制数
N 是16 位,则统计N 的高8 位 和低8 位各自1 的数目a 和b ,而a、b 用某一个16 位数X 存储,则使用0xFF00、0x00FF 分别于X 做与操作,筛选出a 和b ;原问题中的数据是32 位,因此分别需要2 个0xFF00/0x00FF ,即0xFF00FF00/0x00FF00FF 。如果二进制数是
8 位,则统计高4 位和低4 位各自1 的数目,使用0xF0/0x0F 分别做与操作,筛选出高4 位和低4 位;原问题中的数据是32 位,则分别需要4 个0xF0/0x0F ,即0xF0F0F0F0/0x0F0F0F0F 。如果是
4 位则统计高2 位和低2 位各自1 的数目,用0xC/0x3 筛选(高2 位1100 十六进制表示0xC ,低2 位0011 十六进制表示为0x3 );原问题中的数据是32 位,故各需要需要8 个0xC/0x3 ,即0xCCCCCCCC/0x33333333 。如果是
2 位则统计高1 位和低1 位各自1 的数目,用0x2/0x1 筛选;原问题中的数据是32 位,(因为在十六进制中,以四位为一个单位,则高1 位为1010 即为0xA ,需要8 个0xA ,同理低1 位0101 即为0x5 ,也需要8 个 )故各需要8 个0xA/0x3 ,即为0xAAAAAAAA/0x33333333 。
int HammingWeight(unsigned int n){ //(n & 0x55555555)每相邻两位忽略高位保留低位为1的二进制序列, //(n & 0xaaaaaaaa)>>1每相邻两位忽略低位保留高位为1的二进制序列并右移1位,高位补零。 //上面两个子序列相加,则为每相邻两位高位和对应低位为1的相加,往前一位进1。 //也就是检查每对相邻的2位有几个1 n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1); //每相邻的四位有几个1 n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2); //每相邻的八位有几个1 n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4); //每相邻的十六位有几个1 n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8); //32位有几个1 n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16); return n;} int main(){ int c = HammingWeight(16); cout << c << endl;}
在采用
总结与应用
HammingWeight 使用了分治/递归的思想,将问题巧妙解决,降低了运算次数。- 如果定义两个长度相等的
0/1 串中对应位不相同的个数为海明距离(即码距),则某0/1 串和全0 串的海明距离即为这个0/1 串中1 的个数。 - 两个
0/1 串的海明距离,即两个串异或值的1 的数目,因此,该问题在信息编码等诸多领域有广泛应用。
跳跃问题
问题描述
给定非负整数数组,初始时在数组起始位置放置一机器人,数组的每个元素表示在当前位置机器人最大能够跳跃的数目。它的目的是用最少的步数到达数组末端。例如:给定数组
如:
问题分析
由上图我们可以看出当前跳的范围为蓝色的
初始步数
step 赋值为0 ;记当前步的控制范围是
[i,j] ,则用k 遍历i 到j ;
计算A[k]+k 的最大值,记做j2 ;A[k] 表示当前位置最远能跳的距离。step++ ;继续遍历[j+1,j2] ;
每一个
实现代码
int Jump(int* a,int size){ if (size == 1) return 0; int i = 0; int j = 0;//初始可跳的范围即为[i,j] int k,j2; int step = 0; while (j<size) { step++; j2 = j; for (k = i; k <= j; k++)//遍历当前step可跳的范围来确定下一跳的范围 { j2 = max(j2, k + a[k]); if (j2 > size - 1) return step; } i = j + 1;//上一跳的终点的下一个格子为下一跳的起点,注意a[k]为最大可跳的距离,最少可跳一步。 j = j2;//下一跳终点 if (j < i) return -1; } return step;}
Jump问题总结
虽然从代码上看有两层循环,但是我们分析执行过程可知只是从序列头跳到序列尾,时间复杂度只有
该算法在每次跳跃中,都是尽量跳的更远,并记录
错位排列问题
问题描述
问题分析
- 假定
n 个数的错位排列数目为dp[n] - 先考察数字
n 的放置方法:显然,n 可以放在从1 到n−1 的某个位置,共n−1 种方法;假定放在了第k 位。 - 对于数字
k :
要么放置在第n 位
要么不放置在第n 位。
数字k放置在第n位
相当于数字
数字k不放置在第n位
将数字
错位排列递推公式
综上,
初值
只有
只有
则递推公式为:
实现代码
int dislocationSorting(int n){ int* dp = new int[n]; dp--; dp[1] = 0; dp[2] = 1; for (int i = 3; i <= n; i++) dp[i] = (i - 1)*(dp[i - 1] + dp[i - 2]); return dp[n];}int main(){ int c = dislocationSorting(2); cout << c << endl;}
- 算法基础-->概率组合
- java基础算法学习之概率算法
- 【算法基础】排列与组合
- 概率计算- 组合 计数
- 条件概率与组合
- Java编程算法基础---组合与聚合
- Java编程算法基础----组合数学实践
- 概率基础
- 概率算法
- 概率算法
- 概率算法
- 概率算法
- 概率算法
- 概率算法
- 概率算法
- 概率算法
- 概率算法
- 概率算法
- Django入门-1:Django简介和环境搭建
- Linux基础之虚拟内存文件映射mmap
- maven项目tomcat启动报错
- hdu 1688 / poj 3463 #最短路个数
- 排坑,域控中将组策略下发到安全组(group)
- 算法基础-->概率组合
- AS使用JNI生成so简单使用(一)
- html中实现添加水印的功能 / 在jsp页面上直接打开PDF文件
- python成长之路【第十篇】:浅析python select模块
- JFreeChart中文乱码和文字模糊问题的通用解决方案
- Flume搭建测试
- 如何查看OpenCV函数的源代码
- 35:求出e的值
- 【Android】SharedPreferences探索