终于搞清楚了C#二进制的一些关键操作了,解决了微软面试题,求数组中两两之差绝对值最小的值O(N)最少内存限制的问题!
研究了好几天,写出来一个看起来象O(n)的算法,O(nlog)就不用写了.
思路是桶排序O(N)复杂度,为了节省空间,采用了Byte[]数组,1个byte代表8个数字的有无.
回头整理公布一下C#二进制运算的一些重要操作.
研究了好几天,写出来一个看起来象O(n)的算法,O(nlog)就不用写了.
思路是桶排序O(N)复杂度,为了节省空间,采用了Byte[]数组,1个byte代表8个数字的有无.
回头整理公布一下C#二进制运算的一些重要操作.
-
C# code
-
using System; namespace MinABS { class Program { static void Main( string [] args) { int n = 100 ; int [] a = new int [n]; Random rand = new Random(); int min = int .MaxValue; int max = int .MinValue; Console.WriteLine( " 产生了 " + n + " 个数据的实验数组, " ); Console.WriteLine( " 本程序适用于int.MinValue到int.MaxValue范围,请自行修改输入的量和范围 " ); for ( int i = 0 ; i < n; i ++ ) { // 赋值并且取到最大最小值 // a[i] = rand.Next(int.MinValue, int.MaxValue); a[i] = rand.Next( - 100 , 100 ); if (a[i] < min) { min = a[i]; } if (a[i] > max) { max = a[i]; } Console.Write(a[i] + " " ); } Console.WriteLine(); Console.WriteLine( " 在O(n)内得到最大最小分别是: " ); Console.WriteLine(max + " 和 " + min); long offset = ( long )max + Math.Abs(( long )min); // 规划数组的长度。每个byte有8位长 int len = ( int )(offset >> 3 ) + 1 ; Byte[] B = new Byte[len]; int kkkk = 0 ; bool IsSame = false ; // 是否有重合点标记 // O(n)的时间内分配到了Byte[]中。 for ( int i = 0 ; i < n; i ++ ) { offset = ( long )a[i] - ( long )min; int index = ( int )(offset >> 3 ); int temp = B[index]; // 把末k位变成1 // 把右数第k位变成1 例如:(00101001->00101101,k=3) x | (1 << (k-1)) int tempOffSet = ( 1 << ( ( int )(offset & 7 ) ) ); // 判断重合 if ( ! IsSame) { kkkk = temp & tempOffSet; if ((temp & tempOffSet) >= 1 ) { IsSame = true ; // 如果0算最小距离就在这里退出吧。本代码判断重合,但没把0作为结果。 } } int bbb = B[index]; B[index] |= (Byte)(tempOffSet); int aaa = B[index]; } // 最小距离初始为最大。 Console.WriteLine( " 在O(n)的时间内分配到了Byte[]中,正在计算最小距离,请稍候。。。。。 " ); long minABS = long .MaxValue; long lastIndex = - 1 ; // 在常数范围内循环,复杂度不增加。最坏的情况是32*int.MaxValue次。 for ( int i = 0 ; i < B.Length; i ++ ) { // if (B[i] == 0) { continue; } // 在常数范围内循环,复杂度不增加。 for ( int k = 0 ; k < 8 ; k ++ ) { if (((B[i] >> k) & 1 ) == 1 ) { if (lastIndex >= 0 ) { long temp = (( long )i << 3 ) + k - lastIndex; if (temp < minABS) { minABS = temp; Console.WriteLine( " 目前得到了最小距离: " + minABS); } } lastIndex = (i << 3 ) + k; } } } if (IsSame) { Console.WriteLine( " 有重合点 " ); } else { Console.WriteLine( " 无重合点 " ); } Console.WriteLine( " 不考虑重合最小距离是: " + minABS); Console.WriteLine( " 总复杂度是:O(n) " ); Console.ReadLine(); } } }