2进制在组合数学中的应用

有一个字符串数组 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)

理论上是最快的,不信所有同学可以比较一下,几万个字符串的总体计算时间。
我这个应该是瞬间就出结果,而上面那些同学的算法会导致无响应。
因为他们的算法复杂度是几何基数的,输入数字增大,计算量会指数递增。

具体代码我就不写了,只留给有心人,将来可能成为一代教父的天赋者。

悟空,跟我去天竺。。。。。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值