微软面试题,求数组中两两之差绝对值最小的值。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<int> Input = new List<int>();
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<int> 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<int, NumbersInfo> EachNestNum = new Dictionary<int, NumbersInfo>();
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<int> List = new List<int>();
private int key;
public int max = int.MinValue;
public int min = int.MaxValue;
public int count { get { return List.Count; } }
public ulong minresult(Dictionary<int, NumbersInfo> 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;
}
}
}
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<int> Input = new List<int>();
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<int> 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<int, NumbersInfo> EachNestNum = new Dictionary<int, NumbersInfo>();
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<int> List = new List<int>();
private int key;
public int max = int.MinValue;
public int min = int.MaxValue;
public int count { get { return List.Count; } }
public ulong minresult(Dictionary<int, NumbersInfo> 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;
}
}
}