求一条高效的算法
两个字符串,长度都是64的长度,分别存的是"10111010011101..."。我要同位上面进行比较,比如同时为0或者是同时为1,则记录一次相同,求一共有多少个相同的值。
如“100011111”
跟“010010100”
这两个一共4个相同。。
求高效的算法。
只有35分,全给了 --------------------编程问答-------------------- --------------------编程问答-------------------- int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count(); --------------------编程问答-------------------- 用循环对比下标..
--------------------编程问答-------------------- 按位异或运算,然后循环结果,统计值为1的个数 --------------------编程问答-------------------- 扑扑通通的 --------------------编程问答-------------------- 写反了,统计结果为0的个数 --------------------编程问答--------------------
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);
哥,这段代码没有看得懂啊,麻烦解释一哈呢 --------------------编程问答-------------------- 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个字符串,x为r,y为后面的字符串,他们循环各自的比较,如果里面有相等的就把里面的那个字符变成1,不是就是0,然后where==1,就是找那个改变后相等,如果我没猜错的话,你可以吧1都改成2结果也是一样,我指的是函数里的1 --------------------编程问答--------------------
int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();
你这个是语法简洁,更不是高效的算法。 目前看,好像最好的只是到达 O(n) --------------------编程问答--------------------
var cnt = 0
for (var i = 0; i < Math.Min(a.Length, b.Length); i++)
{
if (newHash[i] == oldHash[i])
cnt++;
}
没必要,呵呵他都说是相同长度,不过不明白,楼主为什么不保存成整数。 --------------------编程问答--------------------
int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();
我日 够猛! --------------------编程问答--------------------
按位异或运算,然后循环结果,统计值为1的个数
顶介个...XOR操作 --------------------编程问答--------------------
int r = "100011111".Zip("010010100", (x, y) => x == y ? 1 : 0).Where(x => x == 1).Count();
你这个是语法简洁,更不是高效的算法。 目前看,好像最好的只是到达 O(n)
简洁的算法就是高效,过早优化是错误之源。如果你说这里必须牺牲可读性提高性能,你需要拿出证据证明这是性能瓶颈。再说人家说了,只有“长度是64”。 --------------------编程问答--------------------
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是以数字的方式存储的话,
我上面写的算法只需要几个纳秒就可以结束统计了。 --------------------编程问答--------------------
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次两者也没有丝毫的差别。 --------------------编程问答-------------------- 晕,那要是累计上百万次怎么办? --------------------编程问答--------------------
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楼给出和应该算是最高效的答案了 --------------------编程问答-------------------- 如果想用高效的话就用汇编语言 我记得汇编中就有一个这样比较命令 很久没用呵呵 --------------------编程问答-------------------- 非原创
--------------------编程问答-------------------- c = ~(ia ^ ib);
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;
==>
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;
}
题目:两个字符串,长度都是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在这纯属是唬人的 --------------------编程问答--------------------
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次两者也没有丝毫的差别。
好就是好,
不好就是不好,
嘴硬可不是版主该有的风范 --------------------编程问答--------------------
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#