csdn大笨狼

来源:互联网 发布:mac 重新分配磁盘空间 编辑:程序博客网 时间:2024/06/06 03:08
求二进制数中1的个数以32位无符号整型为例。1: int Count(unsigned x) { 2: x = x - ((x >> 1) & 0x55555555); 3: x = (x & 0x33333333) + ((x >> 2) & 0x33333333); 4: x = (x + (x >> 4)) & 0x0F0F0F0F; 5: x = x + (x >> 8); 6: x = x + (x >> 16); 7: return x & 0x0000003F; 8: } 这里用的是二分法,两两一组相加,之后四个四个一组相加,接着八个八个,最后就得到各位之和了。还有一个更巧妙的HAKMEM算法1: int Count(unsigned x) {2: unsigned n; 3: 4: n = (x >> 1) & 033333333333; 5: x = x - n; 6: n = (n >> 1) & 033333333333; 7: x = x - n; 8: x = (x + (x >> 3)) & 030707070707; 9: x = modu(x, 63); 10: return x; 11: } 首先是将二进制各位三个一组,求出每组中1的个数,然后相邻两组归并,得到六个一组的1的个数,最后很巧妙的用除63取余得到了结果。因为2^6 = 64,也就是说 x_0 + x_1 * 64 + x_2 * 64 * 64 = x_0 + x_1 + x_2 (mod 63),这里的等号表示同余。posted @ 2011-09-05 19:40 CSDN大笨狼 阅读(24) 评论(0) 编辑2011年9月2日主定理(master theorem)主定理(master theorem) T(n)=aT(n/b)+cnab, T(n)=O(nlogba)//b为底 logba 为n的次数你懂得,你不懂,我也没办法。posted @ 2011-09-02 11:18 CSDN大笨狼 阅读(30) 评论(0) 编辑2011年7月22日数据挖掘Demo数据--create table Oders (OdersID int identity(1,1) primary key, UsersID int)--create table OderIterms( OdersID int,ProductID int)--create table Product(ProductID int identity(1,1) primary key , ProductName varchar(50) )--create table Users(UsersID int identity(1,1) primary key,gender bit,age int )--declare @i int--set @i=0------while @i< 10000--begin--insert Users select case when rand()>0.5 then 1 else 0 end as gender,CAST( rand()*100 as int) as age--set @i=@i+1--end----------set @i=0--while @i<10*10000--begin--insert Product select '产品'+ CAST( rand()*100 as varchar) as ProductName--set @i=@i+1--end----------set @i=0--while @i<100*10000--begin--insert Oders select top 1 UsersID as UsersID from Users order by NEWID()--set @i=@i+1--end--declare @i intset @i=0declare @maxUser intselect @maxUser= MAX(UsersID) from Users select CAST( RAND()*@maxUser as int)declare @minUser intselect @minUser=Min(UsersID) from Usersdeclare @maxOders intselect @maxOders= MAX(OdersID) from Odersdeclare @minOders intselect @minOders= Min(OdersID) from Oderswhile @i<1000 10000="" begin="" insert="" oderiterms="" select="" minuser="" cast="" rand="" maxuser="" as="" int="" as="" odersid="" minoders="" cast="" rand="" maxoders="" as="" int="" as="" odersid="" set="" i="@i+1" end="" --select="" count="" from="" dbo="" oderiterms="" --delete="" from="" dbo="" users="" --delete="" from="" dbo="" oderiterms="" --delete="" from="" dbo="" oders="" --delete="" from="" dbo="" product="" --select="" count="" from="" product="" --="" declare="declare" pid="" int="" set="" pid="12345" select="" top="" 10="" a="" productid="" count="" a="" productid="" from="" dbo="" oderiterms="" a="" inner="" join="" dbo="" oders="" b="" on="" a="" productid="" pid="" and="" b="" usersid="" in="" select="" c="" usersid="" from="" dbo="" oders="" c="" inner="" join="" oderiterms="" d="" on="" c="" odersid="D.OdersID" where="" d="" productid="@PID)" group="" by="" a="" productid="" order="" by="" desc="" select="" a="" productid="" productid="" b="" usersid="" usersid="" into="" tb="" from="" oderiterms="" a="" inner="" join="" oders="" b="" on="" a="" odersid="B.OdersID" select="" top="" 1="" a="" productid="" b="" productid="" count="" from="" tb="" a="" inner="" join="" tb="" b="" on="" a="" usersid="B.UsersID" and="" a="" productid="">B.productIDgroup by A.productID,B.productIDorder by count(*) posted @ 2011-07-22 01:14 CSDN大笨狼 阅读(37) 评论(0) 编辑2011年7月20日位运算技巧,继续O(1)的时间,根据前一组合枚举下一组合 using System;namespace ConsoleApplication2{ class Program { static void Main(string[] args) { combian(5, 3); Console.Read(); } static void combian(int n, int k) { if (!(n >= k && k > 0 && n < 30)) { return; } int ik = (1 << k) - 1; while (ik != 0) { // 输出组合 for (int i = 0; i < n; ++i) { if ((ik & (1 << i)) != 0) { Console.Write(i); } } //输出空行分隔之 Console.WriteLine(); ik = next_combination(n, ik); } } static int next_combination(int n, int k) { int ret, b = k & -k, t = (k + b); ret = (((t ^ k) >> 2) / b) | t; if ((1 << ret) < k) { return 0; } else { return ret; } } }}根据k,得到比k大,并且二进制下有相同个数的’1′,而且是当中最小的数比如把1011,变成1101首先,因为1的个数要相同,并且比原数要大,那么,先要找出右起第一次出现1的位置,对这个数加上1,然后在最右边补上少了的1就可以了。找出右起第一次出现1的位置的算法很简单,就是(n & -n),这里的b就是得到这个位置,t就是加了以后的结果,这个应该不难明白,关键的,是后面的计算。后面的计算,主要是针对右边补1的个数,细心想一下,你就知道,要补的1的个数,等于原数右起第一个1向左数,连续的1的个数减1,然后,t^k是什么意思呢?这个就非常有技巧了,它的效果其实和x ^ (x – 1)很类似。而x ^ (x – 1)的作用,是保留右起第一个“1”,同时把右起第1个“1”右边全部变为“1”,类似1101000 -> 1111逆向过来说,就是k = 1100111,对它 +1后,得到t = 1101000,用这个运算可以得到1111,位数和少掉的1成常数差的关系事实上,这样我们变相地得到少掉的1的个数(这个例子中是少了两个1),我们只需要对运算结果中1的个数减2即可,用>>2解决之不过,在当k最右边不是1,有若干个0的时候,前一个步骤得到的数的最右边,就会有同样多的0,如何去掉这些0?这时候,我们最初计算的b,即(n & -n)就太有作用了,只要除以这个b,0就没有了,最后,就是最右边应该补上的值,和前面的t求和,或者求并均可。输出结果是:0 1 20 1 30 2 31 2 30 1 40 2 41 2 40 3 41 3 42 3 4posted @ 2011-07-20 08:00 CSDN大笨狼 阅读(117) 评论(0) 编辑2011年7月10日微软面试题,求数组中两两之差绝对值最小的值。O(n)微软的面试题,我做过。鸽巢原理。using System;using System.Linq;using System.Collections.Generic;namespace ConsoleApplication1{ class Program { static Random Rand = new Random(); static void Main(string[] args) { int count = 10000; List Input = new List(); for (int i = 0; i < count; i++) { Input.Add(Rand.Next(int.MinValue, int.MaxValue)); } ulong re = PigeonNest(Input, ulong.MaxValue); Console.WriteLine(re); Console.WriteLine("-------------"); Console.Read(); } //鸽巢原理。 static ulong PigeonNest(List List, ulong MinResult) { switch (List.Count) { case 0: case 1: return MinResult; case 2: return ABS(List[0], List[1]); default: break; } int min = List.Min(); //确定桶的大小。 int width = (int)Math.Ceiling((double)(List.Max() - min) / List.Count); //不可能比1还小了。 if (width == 1) { return 1ul; } //把数据丢到桶里。 Dictionary EachNestNum = new Dictionary(); foreach (int n in List) { int Key = Convert.ToInt32(Math.Ceiling((double)(n - min) / width)); if (!EachNestNum.ContainsKey(Key)) { EachNestNum.Add(Key, new NumbersInfo(Key)); } EachNestNum[Key].Add(n); } //找到所有桶里,和相邻两桶的最大最小值距离,三个数中最近的。 foreach (int Key in EachNestNum.Keys) { MinResult = Min(MinResult, EachNestNum[Key].minresult(EachNestNum, MinResult)); } return MinResult; } class NumbersInfo { public NumbersInfo(int k) { key = k; } private List List = new List(); private int key; public int max = int.MinValue; public int min = int.MaxValue; public int count { get { return List.Count; } } public ulong minresult(Dictionary EachNestNum, ulong re) { //在三个数中选最小的。 //当命中数大于1的时候,递归这个过程。由于迅速收敛,故复杂度忽略不计。 if (List.Count > 1) { re = PigeonNest(List, re); } if (EachNestNum.ContainsKey(key - 1)) { re = Min(ABS(EachNestNum[key].min, EachNestNum[key - 1].max), re); } if (EachNestNum.ContainsKey(key + 1)) { re = Min(ABS(EachNestNum[key].max, EachNestNum[key + 1].min), re); } return re; } public void Add(int x) { List.Add(x); if (x > max) { max = x; } if (x < min) { min = x; } } } static ulong ABS(int x, int y) { //三分。 switch (x.CompareTo(y)) { case -1: return (ulong)y - (ulong)x; case 1: return (ulong)x - (ulong)y; } return 0ul; } static ulong Min(ulong x, ulong y) { if (x > y) { return y; } return x; } }}posted @ 2011-07-10 01:30 CSDN大笨狼 阅读(171) 评论(1) 编辑阿里巴巴研究院赛马面试题。25匹赛马,5个跑道,也就是说每次有5匹马可以同时比赛。问最少比赛多少次可以知道跑得最快的5匹马?posted @ 2011-07-10 01:23 CSDN大笨狼 阅读(132) 评论(0) 编辑2011年7月6日平面最近点对问题,三分治法。摘要: 最近点对问题,三分治法,和求中位数思路是一样的,1,随机选一个数X,线性扫描,比X小的一堆A,比X大的一堆B,同时可以得到Min=Min(MinB-X,x-MaxA)2, 对于这两堆,分别重复1的步骤,直到结束。求中位数,需要抛弃掉一半数据,只求其中一个子集合的n/2-k大即可。《算法概论》上有证明递推式复杂度的通式。对于递推式T(n)=aT(n/b)+O(n^d)有如下结论:1,当d>log(b,a)时复杂度是O(n^d)2,当d=log(b,a)时复杂度是O(n^d*logn)3, 当d<log(b,a)时复杂度是O(n^(log(b,a))这个公式可以适用于快速排序,中位数等阅读全文posted @ 2011-07-06 17:03 CSDN大笨狼 阅读(328) 评论(0) 编辑2011年7月5日二进制超大整数的秒杀速配摘要: using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Numerics;using System.Globalization;using System.Diagnostics;namespace ConsoleApplication11{ class Program { static int[] HowMuch1 = new int[] { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,阅读全文posted @ 2011-07-05 01:15 CSDN大笨狼 阅读(63) 评论(1) 编辑2011年7月1日成语接龙,哈希表神马的最给力了。摘要: using System;using System.Collections.Generic;using System.IO;using System.Text;namespace ConsoleApplication1{ public class Idiom { public static Dictionary<Char, List> Dict = new Dictionary<char, List>(); public static List IdiomList = new List<Idio阅读全文posted @ 2011-07-01 19:19 CSDN大笨狼 阅读(60) 评论(0) 编辑2011年6月29日再次展示算法的力量!~~三分钟的程序优化到了90毫秒,还是那句话,位运算神马的最给力了。摘要: 再次展示算法的力量!~~三分钟的程序优化到了90毫秒,还是那句话,位运算神马的最给力了。淘宝卖家想知道,哪些商品的组合是最受欢迎的。已知十万多订单项里,有几十种商品,有一万多相关用户,要求输出2-6种商品的全部组合,对应的订单数。订单项,记录的是产品编号,用户编号,可以随机模拟。这个程序,同事小张,在输出2种商品的情况下,就耗时3分多钟。在他原有的代码上,我把他原来的复杂度O(n^2*m^2),利用哈希表,优化到了O(n^2*m),还需要59秒。今天决定得瑟一下,突破性能极限,显露一下位运算的威武。原理如下:63个数以内的排列组合,不管几选几,都可以用一个Ulong整数来表示。比如:
原创粉丝点击