一道算法题
设有两个对象定义如下:
//Item对象的内容分别代表一个存货对象的Id,名称,库存总数量
public class Item{public int ItemId;public string Name;public decimal CountQty;}
//ItemInventory对象的内容分别代表一个存货对象在各个仓库的库存数量
public class ItemInventory{public int ItemId,public int StockId,public decimal Qty;}
有两个数组对象ArrayA[Item]和ArrayB[ItemInventory]分别存储了两个对象列表,两个列表都已经分别按照ItemId字段进行排序,而ArrayA数组中的所有Item对象的CountQty的值为0,请用效率最高的算法将ItemInventory对象的Qty填入到相对应Item对象的CountQty中。
两个对象使用ItemId进行匹配,一个Item对象可能对应着多个ItemInventory对象。
提示:ArrayA和ArrayB都只需要循环一次。
这道题实际上是公司最近的一道内部考核题,为何需要效率最高的算法,源于本人在项目实践中遇到了类似场景。
两个数据实体如下:
在业务中,需要提取出存货对象的基本信息,包含编码,名称之类,也包含了库存。
遇到这个问题时,通常的解决方案是写个SQL语句:
Select Item.ItemId,Number,Name,Sum(Inv.Qty) as CountQty From Item Left join ItemInventory as Inv on Item.ItemId=Inv.ItemId Group by Item.ItemId,Item.Number,Item.Name
但是由于两个表的数据量较大,关联的效率不高,客户界面有明显延时。
于是诞生了题中的问题,事实上,采用了本人认为的最高效率算法之后,提取两个记录级,然后通过算法合并比在SQL中关联查询快了一个数量级。
代码如下:
using System.Collections.Generic;
using System.Diagnostics;
namespace ArrayMerge
{
class Program
{
class Item { public int ItemId; public string Name; public decimal CountQty;}
class ItemInventory { public int ItemId; public int StockId; public decimal Qty;}
static Item[] _arrayA;
static ItemInventory[] _arrayB;
static void CreateDemoData()
{
Console.WriteLine("开始创建演示对象");
_arrayA = new Item[100000];
List<ItemInventory> listB = new List<ItemInventory>();
Random r = new Random();
for (int i = 0; i < _arrayA.Length; i++)
{
_arrayA[i] = new Item { ItemId = i, Name = string.Format("测试对象-{0}", i), CountQty = 0 };
//创建相对应的0~3个ItemInventory对象。
for (int j = 0; j < 3; j++)
{
if (r.Next(100) > 80) break;
listB.Add(new ItemInventory {ItemId = i, StockId = j, Qty = r.Next(1000)});
}
}
_arrayB = listB.ToArray();
Console.WriteLine("演示对象创建完毕,共创建了{0}个Item对象和{1}个ItemInventory对象", _arrayA.Length, _arrayB.Length);
}
private delegate void DoSomething<T1, T2>(T1 a,T2 b);
private delegate int Compare<T1, T2>(T1 a, T2 b);
static void MergeArray<T1,T2>(T1[] arrayA,T2[] arrayB,Compare<T1,T2> compare,DoSomething<T1,T2> mergeAction)
{
int leftPosion = 0, rightPosion = 0;
while(leftPosion<arrayA.Length && rightPosion<arrayB.Length)
{
int compareResult = compare(arrayA[leftPosion], arrayB[rightPosion]);
if(compareResult<0)
{
leftPosion++;
continue;
}
if(compareResult>0)
{
rightPosion++;
continue;
}
if(compareResult==0)
{
mergeAction(arrayA[leftPosion], arrayB[rightPosion]);
rightPosion++;
continue;
}
}
}
static void Main(string[] args)
{
CreateDemoData();
Stopwatch sw = new Stopwatch();
sw.Start();
MergeArray(_arrayA, _arrayB,
(a, b) => a.ItemId.CompareTo(b.ItemId),
(a, b) => a.CountQty += b.Qty
);
sw.Stop();
Console.WriteLine("数据合并完毕,共耗时(毫秒):{0}", sw.ElapsedMilliseconds);
Console.ReadLine();
}
}
}
代码不复杂,一看就明白。只是为了增加算法的通用性,使用了泛型和方法委托。
欢迎指正。