一道算法题

设有两个对象定义如下:

//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都只需要循环一次。

 

这道题实际上是公司最近的一道内部考核题,为何需要效率最高的算法,源于本人在项目实践中遇到了类似场景。

两个数据实体如下:

 A

在业务中,需要提取出存货对象的基本信息,包含编码,名称之类,也包含了库存。

遇到这个问题时,通常的解决方案是写个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;
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> 80break;
                    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();
        }
    }
}

 

 

代码不复杂,一看就明白。只是为了增加算法的通用性,使用了泛型和方法委托。

欢迎指正。

posted @ 2010-08-04 09:16  一味  阅读(355)  评论(0编辑  收藏  举报