2进制在组合数学中的应用
2009-08-19 15:59
246 查看
有一个字符串数组 r=[abc,bac,acb]
我只想保留其中一个组合,也就是说对于字符串内容相同,只是字符组合顺序不同的字符串进行删除。
我给大家介绍一个位运算的技巧,只限制于少于32个字母的情况。
假设字母a的asc码是97,那么我们减去97,这样字母a-z就都编上从0到25的编码了。
a=0;b=1;c=2;d=3;e=4;f=5;g=6....
要判断一个字符串里是否有a,我们可以观察下面的数学算式:
alert(1 < <0);//结果是1
alert(1 < <1);//结果是2
alert(1 < <2);//结果是2
alert(1 < <3);//结果是8
alert(1 < <4);//结果是16
其中 < <代表左移位运算,相当于乘2,移几次就是2的几次方
那么64就代表6,是2的6次方,如果一个字符串的数字计算结果是64,那么这个字符串只能包含6,即只有一个字母g.
65拆成由2的倍数组成的加法式,就是65=64+1=(1 < <6)+(1 < <0),代表里边有6和0组成。
即字母a和f ,a是0,f是6
65=(1 < <6)+(1 < <0)
这个字符串要么是ag要么是ga
观察abc,bac,acb这三个相同的字母组合,按照上面的公式
abc=(1 < <0)+(1 < <1)+(1 < <2)=7;
bac=(1 < <1)+(1 < <0)+(1 < <2)=7;
acb=(1 < <0)+(1 < <2)+(1 < <1)=7;
可以知道7就代表这个字符串的组合情况是abc,有且仅有这几个字母。
以上的字符串组合转数字的方法大家看明白没有?
这个技巧在操作系统内部也是广泛应用的,比如文件的属性
Normal 0 普通文件。不设置属性。
ReadOnly 1 只读文件。属性为读/写。
Hidden 2 隐藏文件。属性为读/写。
System 4 系统文件。属性为读/写。
Volume 8 磁盘驱动器卷标。属性为只读。
Directory 16 文件夹或目录。属性为只读。
Archive 32 文件在上次备份后已经修改。属性为读/写。
Alias 64 链接或者快捷方式。属性为只读。
Compressed 128 压缩文件。属性为只读。
只读是1,隐藏是2,那么即只读又隐藏又是系统文件,就是7,因为7代表1+2+4=(1 < <1)+(1 < <2)+(1 < <3)
判断7里是否包含2,其实很简单,只要进行一次“与”运算:
alert((7 & (1 < <2)) !=0);//true
同样,判断65里是否包含2,0 和6 ,其实很简单,只要进行一次“与”运算:
alert((65 & (1 < <2)) !=0);//false
alert((65 & (1 < <0)) !=0);//true
alert((65 & (1 < <6)) !=0);//true
根据以上的技巧,所有字母是可以编成数字的,所有字符串是可以编成数字的。
所以字符串的组合重复判断,就变成了整数的重复判断。
而整数是否重复出现,你可以采用哈希表复杂度O(N),二叉数复杂度是O(N*log N)
这里给了一个javascript做哈希表的写法,其余代码同学们自己完成就可以了。
<SCRIPT LANGUAGE="JavaScript">
//自定义哈希表类
function Hashtable()
{
this._hash = new Object(); // 创建Object对象
//哈希表的添加方法
this.add = function(key,value){
if(typeof(key)!="undefined"){
if(this.contains(key)==false){
this._hash[key]=typeof(value)=="undefined"?null:value;
return true;
} else {
return false;
}
} else {
return false;
}
}
//哈希表的移除方法
this.remove = function(key){delete this._hash[key];}
//哈希表内部键的数量
this.count = function(){var i=0;for(var k in this._hash){i++;} return i;}
//通过键值获取哈希表的值
this.items = function(key){return this._hash[key];}
//在哈希表中判断某个值是否存在
this.contains = function(key){ return typeof(this._hash[key])!="undefined";}
//清空哈希表内容的方法
this.clear = function(){for(var k in this._hash){delete this._hash[k];}}
}
var myhash=new Hashtable(); //创建哈希表
myhash.add("name","张三"); //添加键和值
alert(myhash.item["name"]); //根据指定键显示哈希表的值
</script>
至于在JS里大搞算法,其实意义不大,不过同样的题目如果出在强语言里,以上思路绝对是追求了速度最快化。
因为理论上复杂度比较小。
还有通过我上边讲的一些思路,加深一下同学们对2进制在组合数学中的应用,以及基本数据结构的认识
以上算法,假设输入字符串总长度是N
进行一次编码复杂度是O(N)
无重复的插入哈希表复杂度是P(N)
总复杂度还是在线性的O(N)+P(N)
理论上是最快的,不信所有同学可以比较一下,几万个字符串的总体计算时间。
我这个应该是瞬间就出结果,而上面那些同学的算法会导致无响应。
因为他们的算法复杂度是几何基数的,输入数字增大,计算量会指数递增。
具体代码我就不写了,只留给有心人,将来可能成为一代教父的天赋者。
悟空,跟我去天竺。。。。。
我只想保留其中一个组合,也就是说对于字符串内容相同,只是字符组合顺序不同的字符串进行删除。
我给大家介绍一个位运算的技巧,只限制于少于32个字母的情况。
假设字母a的asc码是97,那么我们减去97,这样字母a-z就都编上从0到25的编码了。
a=0;b=1;c=2;d=3;e=4;f=5;g=6....
要判断一个字符串里是否有a,我们可以观察下面的数学算式:
alert(1 < <0);//结果是1
alert(1 < <1);//结果是2
alert(1 < <2);//结果是2
alert(1 < <3);//结果是8
alert(1 < <4);//结果是16
其中 < <代表左移位运算,相当于乘2,移几次就是2的几次方
那么64就代表6,是2的6次方,如果一个字符串的数字计算结果是64,那么这个字符串只能包含6,即只有一个字母g.
65拆成由2的倍数组成的加法式,就是65=64+1=(1 < <6)+(1 < <0),代表里边有6和0组成。
即字母a和f ,a是0,f是6
65=(1 < <6)+(1 < <0)
这个字符串要么是ag要么是ga
观察abc,bac,acb这三个相同的字母组合,按照上面的公式
abc=(1 < <0)+(1 < <1)+(1 < <2)=7;
bac=(1 < <1)+(1 < <0)+(1 < <2)=7;
acb=(1 < <0)+(1 < <2)+(1 < <1)=7;
可以知道7就代表这个字符串的组合情况是abc,有且仅有这几个字母。
以上的字符串组合转数字的方法大家看明白没有?
这个技巧在操作系统内部也是广泛应用的,比如文件的属性
Normal 0 普通文件。不设置属性。
ReadOnly 1 只读文件。属性为读/写。
Hidden 2 隐藏文件。属性为读/写。
System 4 系统文件。属性为读/写。
Volume 8 磁盘驱动器卷标。属性为只读。
Directory 16 文件夹或目录。属性为只读。
Archive 32 文件在上次备份后已经修改。属性为读/写。
Alias 64 链接或者快捷方式。属性为只读。
Compressed 128 压缩文件。属性为只读。
只读是1,隐藏是2,那么即只读又隐藏又是系统文件,就是7,因为7代表1+2+4=(1 < <1)+(1 < <2)+(1 < <3)
判断7里是否包含2,其实很简单,只要进行一次“与”运算:
alert((7 & (1 < <2)) !=0);//true
同样,判断65里是否包含2,0 和6 ,其实很简单,只要进行一次“与”运算:
alert((65 & (1 < <2)) !=0);//false
alert((65 & (1 < <0)) !=0);//true
alert((65 & (1 < <6)) !=0);//true
根据以上的技巧,所有字母是可以编成数字的,所有字符串是可以编成数字的。
所以字符串的组合重复判断,就变成了整数的重复判断。
而整数是否重复出现,你可以采用哈希表复杂度O(N),二叉数复杂度是O(N*log N)
这里给了一个javascript做哈希表的写法,其余代码同学们自己完成就可以了。
<SCRIPT LANGUAGE="JavaScript">
//自定义哈希表类
function Hashtable()
{
this._hash = new Object(); // 创建Object对象
//哈希表的添加方法
this.add = function(key,value){
if(typeof(key)!="undefined"){
if(this.contains(key)==false){
this._hash[key]=typeof(value)=="undefined"?null:value;
return true;
} else {
return false;
}
} else {
return false;
}
}
//哈希表的移除方法
this.remove = function(key){delete this._hash[key];}
//哈希表内部键的数量
this.count = function(){var i=0;for(var k in this._hash){i++;} return i;}
//通过键值获取哈希表的值
this.items = function(key){return this._hash[key];}
//在哈希表中判断某个值是否存在
this.contains = function(key){ return typeof(this._hash[key])!="undefined";}
//清空哈希表内容的方法
this.clear = function(){for(var k in this._hash){delete this._hash[k];}}
}
var myhash=new Hashtable(); //创建哈希表
myhash.add("name","张三"); //添加键和值
alert(myhash.item["name"]); //根据指定键显示哈希表的值
</script>
至于在JS里大搞算法,其实意义不大,不过同样的题目如果出在强语言里,以上思路绝对是追求了速度最快化。
因为理论上复杂度比较小。
还有通过我上边讲的一些思路,加深一下同学们对2进制在组合数学中的应用,以及基本数据结构的认识
以上算法,假设输入字符串总长度是N
进行一次编码复杂度是O(N)
无重复的插入哈希表复杂度是P(N)
总复杂度还是在线性的O(N)+P(N)
理论上是最快的,不信所有同学可以比较一下,几万个字符串的总体计算时间。
我这个应该是瞬间就出结果,而上面那些同学的算法会导致无响应。
因为他们的算法复杂度是几何基数的,输入数字增大,计算量会指数递增。
具体代码我就不写了,只留给有心人,将来可能成为一代教父的天赋者。
悟空,跟我去天竺。。。。。
相关文章推荐
- Cayley定理在组合数学中的应用
- BZOJ 3505 浅谈组合数学在图形区域分割问题的应用
- pku 1850 Code 组合数学排列组合的应用
- poj 1026 Cipher (组合数学 置换应用)
- Find a multiple(组合数学:鸽巢原理的简单应用)
- 组合数学之二 —— 容斥原理及应用
- 九度 题目1531 货币面值 (组合数学,母函数应用)
- FZU 2282 Wand (组合数学 错排应用)
- poj 3270 Cow Sorting (组合数学 置换应用)
- 数学之美——组合小事(今天看到的一个简单的组合学应用,但是觉得挺有意思的)
- 山东省第五届省赛题 G - Hearthstone II(简单组合数学应用第二类stirling数)
- Halloween treats(组合数学:鸽巢原理的简单应用)
- 卡特兰数在多种问题下的应用 组合数学-Catalan数
- SPOJ 78 Marbles 组合数学
- USTC OJ — 1003 Fibonacci Numbers(组合数学, 简单题)
- Codeforces Gym 100418K Cards 组合数学
- Vijos P1008 篝火晚会(组合数学,置换群)
- BZOJ3997 TJOI2015 组合数学
- 数学之美 系列七 -- 信息论在信息处理中的应用
- HDU6143 Killer Names 【数学+组合】