zoukankan      html  css  js  c++  java
  • O(A*B)优化到O(A+B)

    先看看代码,很多时候都用到Contains,2个对象相同的取出相同的对象。
    代码片段如下:

    public class Order2
    {
        private int _OrderId { get; set; }
        private string _ProductName{get;set;}
    
        public Order2(int x, string p)
        {
            _OrderId = x;
            _ProductName = p;
        }
    
        public int OrderId
        {
            get { return _OrderId; }
            set { _OrderId = value; }
        }
    
    
        public string ProductName
        {
            get{return _ProductName;}
            set{_ProductName=value;}
        }
    }



    这里的意思是跟据相同的OrderID就可以匹配了,ProductName无需匹配

    /// <summary>
    /// EqualityComparer 规则,详细请看msdn
    /// 用途:并集,交集,差集 Linq 的 IEnumerable 制定特定的规则
    /// </summary>
    public class ComparerRule : IEqualityComparer<Order2>
    {
        public static ComparerRule Defaut = new ComparerRule();
    
        public bool Equals(Order2 x, Order2 y)
        {
            if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
                return false;
    
            return x.OrderId == y.OrderId;
        }
    
        public int GetHashCode(Order2 obj)
        {
    
            if (Object.ReferenceEquals(obj, null)) return 0;
    
            int orderhashcode = obj.OrderId.GetHashCode();
    
            return orderhashcode;
        }
    }
    static void Main(string[] args)
            {
                for (int k = 0; k < 10; k++)
                {
                    List<Order2> A = new List<Order2>();
                    List<Order2> B = new List<Order2>();
    
                    HashSet<Order2> C = new HashSet<Order2>();
    
                    for (int i = 0; i < 10000; i++)
                    {
                        A.Add(new Order2(rand.Next(10000), "产品" + i.ToString()));
                        int temp = rand.Next(10000);
                        B.Add(new Order2(temp, ""));
                        C.Add(new Order2(temp, ""));
                    }
    
                    ////这里复杂度是A*B
                    long T1 = DateTime.Now.Ticks;
                    List<Order2> result1 = new List<Order2>();
                    foreach (Order2 p in A)
                    {
                        if (B.Contains<Order2>(p, ComparerRule.Defaut))
                        {
                            result1.Add(p);
                        }
                    }
                    Console.WriteLine(result1.Count());
                    Console.WriteLine("List执行时间:" + TimeSpan.FromTicks(DateTime.Now.Ticks - T1).Milliseconds + "毫秒");
    
                    ////这里复杂度是A+B
                    long T2 = DateTime.Now.Ticks;
                    List<Order2> result2 = new List<Order2>();
                    foreach (Order2 p in A)
                    {
                        if (C.Contains<Order2>(p, ComparerRule.Defaut))
                        {
                            result2.Add(p);
                        }
                    }
                    Console.WriteLine(result2.Count());
                    Console.WriteLine("HashSet执行时间:" + TimeSpan.FromTicks(DateTime.Now.Ticks - T2).Milliseconds + "毫秒");
                
                }
                Console.Read();
            }


    看下执行结果,并没有感觉hashset提升了多少效果。估计跟IEqualityComparer接口有关系。
    $KR}R}][@P`VS_VT1D@A`F8



    代码进一步修改。

    public class ABContains
        {
            public static List<Order2> Contains(List<Order2> I1, List<Order2> I2)
            {
                var list = Array.ConvertAll<Order2, long>(I2.ToArray(), delegate(Order2 output)
                {
                    return output.OrderId;
                });
    
    
                HashSet<long> Target = new HashSet<long>(list);
    
    
                List<Order2> Result = new List<Order2>();
    
                foreach (Order2 p in I1)
                {
                    if (Target.Contains(p.OrderId))
                    {
                        Result.Add(p);
                    }
                }
    
                return Result;
            }
        }
                long T3 = DateTime.Now.Ticks;
                List<Order2> o = ABContains.Contains(A, B);
                Console.WriteLine(o.Count());
                Console.WriteLine("ABContains执行时间:" + TimeSpan.FromTicks(DateTime.Now.Ticks - T3).Milliseconds + "毫秒");
    ……


    执行结果,其中有一部分是转换花的时间,效果显而易见。

    I5U)7CG81U{)`_85~L{K2G5

  • 相关阅读:
    lightoj-1050
    lightoj-1305
    lightoj-1354
    lightoj-1433
    lightoj-1227
    lightoj-1189
    lightoj-1182
    lightoj-1011
    lightoj-1009
    lightoj-1023
  • 原文地址:https://www.cnblogs.com/kfsmqoo/p/5120862.html
Copyright © 2011-2022 走看看