C# 以下两种方法返回正确的结果,但性能测试失败

C# 以下两种方法返回正确的结果,但性能测试失败,c#,performance,for-loop,iteration,C#,Performance,For Loop,Iteration,我正在编写这个方法,并尝试用两种方法编写它,但是这个方法没有通过性能测试 方法问题:编写一个函数,当传递一个列表和一个目标和时,该函数根据使用的时间高效地返回任意两个数字的两个不同的从零开始的索引,其和等于目标和。如果没有两个数字,函数应该返回null 例如,FindTwoSum(new List(){3,1,5,7,5,9},10)应该返回一个元组,其中包含以下任何一对索引: 0和3(或3和0)等于3+7=10 1和5(或5和1)等于1+9=10 2和4(或4和2)等于5+5=10 usin

我正在编写这个方法,并尝试用两种方法编写它,但是这个方法没有通过性能测试

方法问题:编写一个函数,当传递一个列表和一个目标和时,该函数根据使用的时间高效地返回任意两个数字的两个不同的从零开始的索引,其和等于目标和。如果没有两个数字,函数应该返回null

例如,FindTwoSum(new List(){3,1,5,7,5,9},10)应该返回一个元组,其中包含以下任何一对索引:

  • 0和3(或3和0)等于3+7=10
  • 1和5(或5和1)等于1+9=10
  • 2和4(或4和2)等于5+5=10

    using System;
    using System.Collections.Generic;
    using System.Linq;
    class TwoSum
    {
    public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
    {
        int? item1Index = null;
        int? item2Index = null;
    
        var len = list.Count;
        int i = 0;
        while (i < len)
        {
            var j = i + 1;
            while (j < len)
            {
                if ((list[i] + list[j]).Equals(sum))
                {
                    item1Index = i;
                    item2Index = j;
                    break;
                }
                j++;
            }
            i++;
        }
        if (item1Index.HasValue && item2Index.HasValue)
            return new Tuple<int, int>(item1Index.Value, item2Index.Value);
    
        return null;
    }
    
    public static Tuple<int, int> FindTwoSum2(IList<int> list, int sum)
    {
        int? item1Index = null;
        int? item2Index = null;
    
    
        var result = (from list1 in list.Select((i,idx)=> new { item= i, index = idx})
                      from list2 in list.Select((i, idx) => new { item = i, index = idx })
                      select new
                      {
                          ListOneItem = list1.item,
                          ListOneItemIndex = list1.index,
                          ListTwoItem = list2.item,
                          ListTwoItemIndex = list2.index
                      }).Where(c => c.ListOneItemIndex != c.ListTwoItemIndex 
                                    && (c.ListOneItem + c.ListTwoItem).Equals(sum))
    
                        .FirstOrDefault();
        if (result != null)
            return new Tuple<int, int>(result.ListOneItemIndex, result.ListTwoItemIndex);
        return null;       
    }
    
    public static void Main(string[] args)
    {
        Tuple<int, int> indices = FindTwoSum(new List<int>() { 3, 1, 5, 7, 5, 9 }, 10);
        if (indices != null)
        {
            Console.WriteLine(indices.Item1 + " " + indices.Item2);
        }
    }  
    }
    
    使用系统;
    使用System.Collections.Generic;
    使用System.Linq;
    第二类和
    {
    公共静态元组FindTwoSum(IList列表,int-sum)
    {
    int?item1Index=null;
    int?item2Index=null;
    var len=list.Count;
    int i=0;
    而(我new{item=i,index=idx})
    从列表中的列表2中选择((i,idx)=>new{item=i,index=idx})
    选择新的
    {
    ListOneItem=list1.item,
    ListOneItemIndex=list1.index,
    ListTwoItem=list2.item,
    ListTwoItemIndex=list2.index
    }).Where(c=>c.ListOneItemIndex!=c.ListTwoItemIndex
    &&(c.ListOneItem+c.ListTwoItem)。等于(和)
    .FirstOrDefault();
    如果(结果!=null)
    返回新元组(result.ListOneItemIndex,result.ListTwoItemIndex);
    返回null;
    }
    公共静态void Main(字符串[]args)
    {
    Tuple index=FindTwoSum(newlist(){3,1,5,7,5,9},10);
    如果(索引!=null)
    {
    Console.WriteLine(index.Item1+“”+index.Item2);
    }
    }  
    }
    

您应该
返回
而不是
从内部
中断
,否则,代码将通过外部
while
循环评估所有组合

此外,您还可以遵循下面的最佳方法,该方法使用基于字典的方法在一次过程中(在一个while循环中)计算总和

有关代码的详细信息:

  • 下面的程序支持使用
    字典
    快速查找
  • 该列表被迭代并将元素插入到字典中,它还会回过头来检查字典中是否已经存在当前元素的补码。我
  • 程序检查每个元素的补码(target-nums[i])是否存在于
    字典中。如果它存在,那么这就是解决方案,并立即返回它

    public static Tuple<int, int> FindTwoSum(int[] nums, int target) {
      Dictionary<int, int> hashData = new Dictionary<int, int>();
      for (int index = 0; index < nums.Length; index++)
      {
        int remainingTarget = target - nums[index];
        if (hashData.ContainsKey(remainingTarget))
        {
            return new Tuple<int, int>(hashData[remainingTarget], index);
        }
        else
        {
            if (!hashData.ContainsKey(nums[index]))
            {
                hashData.Add(nums[index], index);
            }
         }
     }
    
      return null;
    }
    
    公共静态元组FindTwoSum(int[]nums,int目标){
    Dictionary hashData=新字典();
    对于(int index=0;index

由于列表的每个元素只遍历一次,所以这个程序的时间复杂度是
O(n)
。表中的每次查找仅花费O(1)O(1)次。

当大量项传递给此方法时,它失败的是什么“性能测试”。测试:result.Count()>0而不是null。“超时”-代码没有计时机制。你用什么来计时?您是否正在使用一些测试框架?这只是“花了很长时间才能完成”吗?听起来像是一个在线编码测试。您的第一个方法应该在找到解决方案后立即返回,而不是尝试每个组合。谢谢,此解决方案已通过我的性能测试。仅供参考,请修复此代码中的小错误,以便我可以将其标记为答案。thanks@jNet-小错误是什么?描述一下它是如何工作的可能很有用:给定目标总数=T:对于每个数字N,如果[N-T]存在,那么我们有两个加在T上的数字,即N和N-T。我们通过在哈希表中查找[N-T]来确定它是否存在,这使得该算法的复杂性为O(N)。我们可以在迭代所有数字时向哈希表中添加数字,因此只有一个循环。@MatthewWatson-当然。让我补充一下描述。