当前位置:编程学习 > C#/ASP.NET >>

求一条高效的算法

两个字符串,长度都是64的长度,分别存的是"10111010011101..."。
我要同位上面进行比较,比如同时为0或者是同时为1,则记录一次相同,求一共有多少个相同的值。
如“100011111”
跟“010010100”
这两个一共4个相同。。

求高效的算法。
只有35分,全给了 --------------------编程问答-------------------- --------------------编程问答-------------------- int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count(); --------------------编程问答-------------------- 用循环对比下标.. 

            int count = 0;
            string str1 = "100011111";
            string str2 = "010010100";
            for (int i = 0; i < str1.Length; i++)
                if (str1[i].Equals(str2[i]))
                    count++;
            Console.WriteLine(count);
--------------------编程问答-------------------- 按位异或运算,然后循环结果,统计值为1的个数 --------------------编程问答--------------------
引用 2 楼 caozhy 的回复:
int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();
扑扑通通的 --------------------编程问答-------------------- 写反了,统计结果为0的个数 --------------------编程问答--------------------
引用 2 楼 caozhy 的回复:
int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();


哥,这段代码没有看得懂啊,麻烦解释一哈呢 --------------------编程问答-------------------- int r = "100011111".Zip("010010100", (x, y) => x == y).Where(x => x).Count();
就可以了。 --------------------编程问答-------------------- 一个for就行了 要什么高效算法?  --------------------编程问答--------------------     var cnt = 0
    for (var i = 0; i < Math.Min(a.Length, b.Length); i++)
    {
        if (newHash[i] == oldHash[i])
            cnt++;
    }
--------------------编程问答-------------------- a-> newHash
b-> oldHash

基本上#3楼的for循环比较。不过那个代码忘记了 Math.Min 计算,需要补充上。 --------------------编程问答--------------------
引用 2 楼 caozhy 的回复:
int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();
厉害高手啊,愣是没看懂 --------------------编程问答--------------------
引用 12 楼 xjzggzg 的回复:
Quote: 引用 2 楼 caozhy 的回复:

int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();
厉害高手啊,愣是没看懂

比较2个字符串,x为r,y为后面的字符串,他们循环各自的比较,如果里面有相等的就把里面的那个字符变成1,不是就是0,然后where==1,就是找那个改变后相等,如果我没猜错的话,你可以吧1都改成2结果也是一样,我指的是函数里的1 --------------------编程问答--------------------
引用 2 楼 caozhy 的回复:
int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();


你这个是语法简洁,更不是高效的算法。 目前看,好像最好的只是到达 O(n) --------------------编程问答--------------------
引用 10 楼 sp1234 的回复:
    var cnt = 0
    for (var i = 0; i < Math.Min(a.Length, b.Length); i++)
    {
        if (newHash[i] == oldHash[i])
            cnt++;
    }


没必要,呵呵他都说是相同长度,不过不明白,楼主为什么不保存成整数。 --------------------编程问答--------------------
引用 2 楼 caozhy 的回复:
int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();

我日  够猛! --------------------编程问答--------------------
引用 4 楼 foxflyhigher 的回复:
按位异或运算,然后循环结果,统计值为1的个数



顶介个...XOR操作 --------------------编程问答--------------------
引用 14 楼 Linux7985 的回复:
Quote: 引用 2 楼 caozhy 的回复:

int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();


你这个是语法简洁,更不是高效的算法。 目前看,好像最好的只是到达 O(n)


简洁的算法就是高效,过早优化是错误之源。如果你说这里必须牺牲可读性提高性能,你需要拿出证据证明这是性能瓶颈。再说人家说了,只有“长度是64”。 --------------------编程问答--------------------
引用 18 楼 caozhy 的回复:
Quote: 引用 14 楼 Linux7985 的回复:

Quote: 引用 2 楼 caozhy 的回复:

int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();


你这个是语法简洁,更不是高效的算法。 目前看,好像最好的只是到达 O(n)


简洁的算法就是高效,过早优化是错误之源。如果你说这里必须牺牲可读性提高性能,你需要拿出证据证明这是性能瓶颈。再说人家说了,只有“长度是64”。


你这个不是简洁的算法,是简洁的语法。 从算法的效率上讲,这个Linq是不可取的。 当然了,现在只有64个字节长度。 可能差别不是太大。不过我还是有兴趣比较一下两个算法的时间差。 --------------------编程问答--------------------

Stopwatch s = new Stopwatch();
var a = "1000111110001111100011111000111110001111100011111000111110001111";
var b = "0100101000100101000100101000100101000100101000100101000100101000";
s.Start();
var ia = Convert.ToUInt64(a, 2);
var ib = Convert.ToUInt64(b, 2);
var c = ~(ia ^ ib);
c = (c & 0x5555555555555555) + ((c >> 1) & 0x5555555555555555);  // 相伶1位相加
c = (c & 0x3333333333333333) + ((c >> 2) & 0x3333333333333333);  // 相伶2位相加 
c = (c & 0x0F0F0F0F0F0F0F0F) + ((c >> 4) & 0x0F0F0F0F0F0F0F0F);  // 相伶4位相加
c = (c & 0x00FF00FF00FF00FF) + ((c >> 8) & 0x00FF00FF00FF00FF);  // 相伶8位相加
c = (c & 0x0000FFFF0000FFFF) + ((c >> 16) & 0x0000FFFF0000FFFF);  // 相伶16位相加
c = (c & 0x00000000FFFFFFFF) + ((c >> 32) & 0x00000000FFFFFFFF);  // 相伶16位相加
s.Stop();
var one = s.Elapsed;


s.Restart();
int r = a.Zip(b, (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();
s.Stop();
var two = s.Elapsed; 


求出来的长度都是r=29,c=29,可是所用的时间就是天地之别了
one=0.0000109 秒
two=0.0062630 秒
这还只是一次计算。
自己测一下吧。 --------------------编程问答-------------------- 如果楼主的64位的010101是以数字的方式存储的话,
我上面写的算法只需要几个纳秒就可以结束统计了。 --------------------编程问答--------------------
引用 20 楼 Linux7985 的回复:

Stopwatch s = new Stopwatch();
var a = "1000111110001111100011111000111110001111100011111000111110001111";
var b = "0100101000100101000100101000100101000100101000100101000100101000";
s.Start();
var ia = Convert.ToUInt64(a, 2);
var ib = Convert.ToUInt64(b, 2);
var c = ~(ia ^ ib);
c = (c & 0x5555555555555555) + ((c >> 1) & 0x5555555555555555);  // 相伶1位相加
c = (c & 0x3333333333333333) + ((c >> 2) & 0x3333333333333333);  // 相伶2位相加 
c = (c & 0x0F0F0F0F0F0F0F0F) + ((c >> 4) & 0x0F0F0F0F0F0F0F0F);  // 相伶4位相加
c = (c & 0x00FF00FF00FF00FF) + ((c >> 8) & 0x00FF00FF00FF00FF);  // 相伶8位相加
c = (c & 0x0000FFFF0000FFFF) + ((c >> 16) & 0x0000FFFF0000FFFF);  // 相伶16位相加
c = (c & 0x00000000FFFFFFFF) + ((c >> 32) & 0x00000000FFFFFFFF);  // 相伶16位相加
s.Stop();
var one = s.Elapsed;


s.Restart();
int r = a.Zip(b, (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();
s.Stop();
var two = s.Elapsed; 


求出来的长度都是r=29,c=29,可是所用的时间就是天地之别了
one=0.0000109 秒
two=0.0062630 秒
这还只是一次计算。
自己测一下吧。

0和0.1秒都在人类感知时间范围之外。因此算100次两者也没有丝毫的差别。 --------------------编程问答-------------------- 晕,那要是累计上百万次怎么办? --------------------编程问答--------------------
Quote: 引用 20 楼 Linux7985 的回复:


Stopwatch s = new Stopwatch();
var a = "1000111110001111100011111000111110001111100011111000111110001111";
var b = "0100101000100101000100101000100101000100101000100101000100101000";
s.Start();
var ia = Convert.ToUInt64(a, 2);
var ib = Convert.ToUInt64(b, 2);
var c = ~(ia ^ ib);
c = (c & 0x5555555555555555) + ((c >> 1) & 0x5555555555555555);  // 相伶1位相加
c = (c & 0x3333333333333333) + ((c >> 2) & 0x3333333333333333);  // 相伶2位相加 
c = (c & 0x0F0F0F0F0F0F0F0F) + ((c >> 4) & 0x0F0F0F0F0F0F0F0F);  // 相伶4位相加
c = (c & 0x00FF00FF00FF00FF) + ((c >> 8) & 0x00FF00FF00FF00FF);  // 相伶8位相加
c = (c & 0x0000FFFF0000FFFF) + ((c >> 16) & 0x0000FFFF0000FFFF);  // 相伶16位相加
c = (c & 0x00000000FFFFFFFF) + ((c >> 32) & 0x00000000FFFFFFFF);  // 相伶16位相加
s.Stop();
var one = s.Elapsed;


s.Restart();
int r = a.Zip(b, (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();
s.Stop();
var two = s.Elapsed; 

高手啊 话说我都看不懂 --------------------编程问答-------------------- 这个题本身很简单,不可能做不出,楼主是来求高效的算法的,3楼给出和应该算是最高效的答案了 --------------------编程问答-------------------- 如果想用高效的话就用汇编语言 我记得汇编中就有一个这样比较命令 很久没用呵呵 --------------------编程问答-------------------- 非原创

var a = "1000111110001111100011111000111110001111100011111000111110001111";
var b = "0100101000100101000100101000100101000100101000100101000100101000";
ulong ia = Convert.ToUInt64(a, 2);
ulong ib = Convert.ToUInt64(b, 2);
c = ~(ia ^ ib);
ulong count = 0;
for (int i = 0; i < 8; i++)
{
     count += c & 0x0101010101010101L;
     c >>= 1;
}
count += (count >> 32);
count += (count >> 16);
count += (count >> 8);
count &= 0xff;
--------------------编程问答-------------------- c = ~(ia ^ ib);
==>
ulong c = ~(ia ^ ib); --------------------编程问答-------------------- 题目:两个字符串,长度都是64的长度

最容易理解的写法

var a = "0011110000000000000000000001100010100000000000000000000000000100";
var b = "1010010000000000000000000001100010100000000000000000000000000000";
ulong ia = Convert.ToUInt64(a, 2);
ulong ib = Convert.ToUInt64(b, 2);
ulong ic = ~(ia ^ ib);
ulong count = 0;
for (int i = 0; i < 64; i++)
{
    count += c & 0x0000000000000001L;
    c >>= 1;
}
--------------------编程问答--------------------
引用 29 楼 hwenycocodq520 的回复:
题目:两个字符串,长度都是64的长度

最容易理解的写法

var a = "0011110000000000000000000001100010100000000000000000000000000100";
var b = "1010010000000000000000000001100010100000000000000000000000000000";
ulong ia = Convert.ToUInt64(a, 2);
ulong ib = Convert.ToUInt64(b, 2);
ulong ic = ~(ia ^ ib);
ulong count = 0;
for (int i = 0; i < 64; i++)
{
    count += c & 0x0000000000000001L;
    c >>= 1;
}


但是其实并不是最高效的,因为他是字符串,如果数据存成一个长整型的话,这样的效率是非常高的。
所以,唯一高效的就是3楼的算法, 因为只是64循环就Ok了。
你的算法和我的算法都有一个问题就是需要先转换成长整型,这样就相当于循环了两次64.也就是O(2n)
所以这个算法所花时间是3楼的2倍左右,因为多了一次循环,而统计的相同位数的核心代码却几乎不花时间。 --------------------编程问答-------------------- 还有比直接比较更高效的算法吗?
还是3楼最简洁实用,linq在这纯属是唬人的 --------------------编程问答--------------------
引用 22 楼 caozhy 的回复:
Quote: 引用 20 楼 Linux7985 的回复:


Stopwatch s = new Stopwatch();
var a = "1000111110001111100011111000111110001111100011111000111110001111";
var b = "0100101000100101000100101000100101000100101000100101000100101000";
s.Start();
var ia = Convert.ToUInt64(a, 2);
var ib = Convert.ToUInt64(b, 2);
var c = ~(ia ^ ib);
c = (c & 0x5555555555555555) + ((c >> 1) & 0x5555555555555555);  // 相伶1位相加
c = (c & 0x3333333333333333) + ((c >> 2) & 0x3333333333333333);  // 相伶2位相加 
c = (c & 0x0F0F0F0F0F0F0F0F) + ((c >> 4) & 0x0F0F0F0F0F0F0F0F);  // 相伶4位相加
c = (c & 0x00FF00FF00FF00FF) + ((c >> 8) & 0x00FF00FF00FF00FF);  // 相伶8位相加
c = (c & 0x0000FFFF0000FFFF) + ((c >> 16) & 0x0000FFFF0000FFFF);  // 相伶16位相加
c = (c & 0x00000000FFFFFFFF) + ((c >> 32) & 0x00000000FFFFFFFF);  // 相伶16位相加
s.Stop();
var one = s.Elapsed;


s.Restart();
int r = a.Zip(b, (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();
s.Stop();
var two = s.Elapsed; 


求出来的长度都是r=29,c=29,可是所用的时间就是天地之别了
one=0.0000109 秒
two=0.0062630 秒
这还只是一次计算。
自己测一下吧。

0和0.1秒都在人类感知时间范围之外。因此算100次两者也没有丝毫的差别。


好就是好,
不好就是不好,
嘴硬可不是版主该有的风范 --------------------编程问答--------------------
引用 32 楼 wwwspider001 的回复:
Quote: 引用 22 楼 caozhy 的回复:

Quote: 引用 20 楼 Linux7985 的回复:


Stopwatch s = new Stopwatch();
var a = "1000111110001111100011111000111110001111100011111000111110001111";
var b = "0100101000100101000100101000100101000100101000100101000100101000";
s.Start();
var ia = Convert.ToUInt64(a, 2);
var ib = Convert.ToUInt64(b, 2);
var c = ~(ia ^ ib);
c = (c & 0x5555555555555555) + ((c >> 1) & 0x5555555555555555);  // 相伶1位相加
c = (c & 0x3333333333333333) + ((c >> 2) & 0x3333333333333333);  // 相伶2位相加 
c = (c & 0x0F0F0F0F0F0F0F0F) + ((c >> 4) & 0x0F0F0F0F0F0F0F0F);  // 相伶4位相加
c = (c & 0x00FF00FF00FF00FF) + ((c >> 8) & 0x00FF00FF00FF00FF);  // 相伶8位相加
c = (c & 0x0000FFFF0000FFFF) + ((c >> 16) & 0x0000FFFF0000FFFF);  // 相伶16位相加
c = (c & 0x00000000FFFFFFFF) + ((c >> 32) & 0x00000000FFFFFFFF);  // 相伶16位相加
s.Stop();
var one = s.Elapsed;


s.Restart();
int r = a.Zip(b, (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();
s.Stop();
var two = s.Elapsed; 


求出来的长度都是r=29,c=29,可是所用的时间就是天地之别了
one=0.0000109 秒
two=0.0062630 秒
这还只是一次计算。
自己测一下吧。

0和0.1秒都在人类感知时间范围之外。因此算100次两者也没有丝毫的差别。


好就是好,
不好就是不好,
嘴硬可不是版主该有的风范


真不是“嘴硬”。真不觉得好在哪里。
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,