csdn大笨狼

求二進制數中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整數來表示。比如:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章