二幂拆分问题
来源:互联网 发布:d3.js官网demo 编辑:程序博客网 时间:2024/06/15 00:57
转载请注明出处,http://blog.csdn.net/Bule_Zst/article/details/77111983
问题描述:
任意一个整数x都可以写成一系列2的幂的组合,这里的组合是指用加减法把它们接连起来。令f(x)为x需要的最少的2的幂的项数,求f(x)。
如:
声明:
因为
下面介绍三种算法,由易到难,且算法之间存在联系。
算法1:
令floor2(x)表示不大于x的最大2幂, ceil2(x)表示不小于x的最小2幂,最优的组合要么是floor2(x)加上其它一些项,或者是ceil2(x)减去其它一些项。
于是可以得到求f(x)的一个递归过程如下:
def f(x): if x == 0: return 0 l = floor2(x) u = ceil2(x) if l == u: return 1 return 1 + min(f(x - l), f(u - x))
算法2:
观察算法1会发现,有很多的计算都是重复的
如对于对于求
测试代码:
def floor2( x ): a = 1 while a < x: a = a * 2 if a == x: return a else: return a / 2def ceil2( x ): a = 1 while a < x: a = a * 2 return adef f(x): print x if x == 0: return 0 l = floor2(x) u = ceil2(x) if l == u: return 1 return 1 + min(f(x - l), f(u - x))print f( 23 )
因此可以使用一个数组存储已经计算过的结果:
def f(x): if x == 0: return 0 if x in table: return table[x] l = floor2(x) u = ceil2(x) if l == u: return 1 r = 1 + min(f(x - l), f(u - x)) table[x] = r return r
算法3:
算法2是一个从本身串层层向下递推的过程,因此需要额外内存存储结果,因此想到,可以改进算法2为由下向上的过程。
分析算法2的递推过程:
如
我们会发现,
因此,算法3的思路就是,从右往左遍历自身串,用u表示以1开头的串的
从右往左扫,扫到1则更新u,扫到0则更新d
自身串最右边刚开始的那些0是没有用的,一直扫到1开始更新,u、d赋初值1
代码中的>>1不要当成除以2,而是看做二进制字符串的右移。&1 == 1表示最后一位是1.
def f(x): if x == 0: return 0 while x & 1 == 0: x = x >> 1 u = 1 d = 1 x = x >> 1 while x > 0: if x & 1 == 1: u = min(u, d) + 1 else: d = min(u, d) + 1 x = x >> 1 return u
2017年9月6日更新
今天重新看了这篇文章,发现自己竟然看不懂了,what?现在终于又懂了,再把思路重新梳理一下。
前两个方法没什么好说的,关键是第三个方法,里面的u与v。
u指的是当前二进制字符串(以1开头)从左往右第二个1开头的新串的
举个例子就懂了,这个方法确实很神奇
1010110
初始,
u: 10: 1
v: 10: 1
PS:10表示代表的串,1表示需要二进制数的个数
计算110,因为1开头,所以更新u
或
结果:u: 110: 2
计算1010(原串:0110),更新v
或
结果:v: 1010: 2
计算10110,更新u
或
结果:u: 10110: 3
计算101010(原串:010110),更新v
或
以此类推
参考文章:
http://blog.csdn.net/howardemily/article/details/74938030
http://blog.csdn.net/howardemily/article/details/74938033
- 二幂拆分问题
- 二幂拆分问题
- hihocoder #1527 : 快速乘法(二幂拆分)
- 自然数拆分问题
- 整数拆分问题
- 整数拆分问题
- 文件拆分的问题
- 静态拆分窗口问题
- 硬币拆分问题。
- 整数拆分问题
- 整数的拆分问题
- 整数拆分问题
- 整数拆分问题详解
- 整数的拆分问题
- 整数拆分问题
- 整数拆分问题
- Java字符串拆分问题
- 分数拆分问题
- 各编码格式略谈
- 30分钟,搭建你的个人网站 | github.io
- 详解C#break ,continue, return
- va_list原理及用法
- ssm分布式架构电商项目(五)
- 二幂拆分问题
- jdk源码分析--了解class文件
- NYOJ 【108】士兵杀敌 一 (线段树 + 模板题)
- STM32在IAR和MDK中使用printf进行串口打印的实现方法
- Drying (二分法)
- python网络爬虫与信息采取之解析网页(二)---BeautifulSoup库的find()和find_all()
- 递归简论
- JAVA深入研究——Method的Invoke方法。
- poj 2065 SETI(高斯消元)