在c#中找到两个求和函数

时间:2016-04-08 17:51:16

标签: c#

我正在尝试解决testdome在线考试中的问题。

问题是写一个函数,给定一个列表和一个目标和,返回任何两个不同元素的从零开始的索引,其总和等于目标总和。如果没有这样的元素,函数应该返回null。

这是我的代码,它只有75%为真,25%对时间超过

using System;
using System.Linq;
using System.Collections.Generic;

class TwoSum
{
    public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
    {
        var result = from n1 in list
                     from n2 in list
                     where n1 + n2 == sum
                     select new Tuple<int, int>(list.IndexOf(n1), list.IndexOf(n2));
        return result.FirstOrDefault();
    }
    public static void Main(string[] args)
    {
        Tuple<int, int> indices = FindTwoSum(new List<int>() { 1, 3, 5, 7, 9 }, 12);
        Console.WriteLine(indices.Item1 + " " + indices.Item2);
    }
}

您可以将我的代码粘贴到在线网站上并查看结果。 任何人都可以帮助我,所以我们100%真实。 :D

https://www.testdome.com/Questions/Csharp/TwoSum/4318

12 个答案:

答案 0 :(得分:4)

这是您需要通过其他方法解决问题的案例之一。而不是对所有值进行交叉连接并找到匹配的第一个总和,而是要查找所有值并循环并检查当前项和总和的差异是否在该查找中。这样就可以得到最差的线性性能而不是多项式。

public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
    var lookup = list.Select((x, i) => new { Index = i, Value = x })
                     .ToLookup(x => x.Value, x => x.Index);
    for (int i = 0; i < list.Count; i++)
    {
        int diff = sum - list[i];
        if (lookup.Contains(diff))
            return Tuple.Create(i, lookup[diff].First());
    }

    return null;
}

答案 1 :(得分:4)

使用HashSet而不是LookUp稍微修改代码。

public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
    var hs = new HashSet<int>();
    list.ToList().ForEach(x => hs.Add(x));

    for (int i = 0; i < hs.Count; i++)
    {
        var diff = sum - list[i];
        if (hs.Contains(diff))
        {
            var index = list.IndexOf(diff);
            return new Tuple<int, int>(i, index);
        }
    }

    return null;
}
  

我已经尝试并测试并获得100%,即所有测试都通过,包括   &#34;具有大量元素的性能测试&#34;测试

答案 2 :(得分:3)

Atif的解决方案稍作修改,我们不需要先将列表复制到HashSet。

public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
    HashSet<int> hs = new HashSet<int>();
    for (int i = 0; i < list.Count; i++)
    {
        var needed = sum - list[i];
        if (hs.Contains(needed))
        {
            return Tuple.Create(list.IndexOf(needed), i);
        }
        hs.Add(list[i]);                
    }
    return null;
}

答案 3 :(得分:2)

public static Tuple<int, int> FindTwoSum(IList<int> list, int target)
{
    var dict = new Dictionary<int, int>();
    for (int i = 0; i < list.Count; i++)
    {
        var diff = target - list[i];
        int j = -1;
        if(dict.TryGetValue(diff, out j))
        {
            return Tuple.Create<int, int>(j, i);
        }

        dict[list[i]] = i;
    }

    return null;
}

答案 4 :(得分:1)

对您的版本稍作修改也会通过测试。但这不是100%正确。这告诉你Testdome上的测试用例不完整。我将把它留作一个错误的练习。

    public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
    {
        var result = from n1 in list
                     join n2 in list
                     on n1 equals sum - n2
                     select new Tuple<int, int>(list.IndexOf(n1), list.IndexOf(n2));
        return result.FirstOrDefault(x=>x.Item1!=x.Item2);
    }

答案 5 :(得分:1)

使用juharr代码版本的非Linq扩展方法

    public static Tuple<int, int> FindTwoSumImprovedNonLinq(IList<int> list, int sum)
    {          
        for (int i = 0; i < list.Count; i++)
        {
            int diff = sum - list[i];
            if (list.IndexOf(diff) > -1)
                return Tuple.Create(i, list.IndexOf(diff));
        }

        return null;
    }

答案 6 :(得分:1)

这是我的工作解决方案:

public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
    var dictionary = new Dictionary<int, int>();

    for (var i = 0; i < list.Count; i++)
    {
        var aim = sum - list[i];

        if(dictionary.ContainsKey(aim))
        {
            return new Tuple<int, int> (dictionary[aim], i);
        }
        else if(!dictionary.ContainsKey(list[i]))
        {
            dictionary.Add(list[i], i);
        }
    }

    return null;
}

答案 7 :(得分:1)

public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
    int max = list.Max();
    for (int i = 0; i < list.Count - 1; i++)
    {
        int first = list[i];

        if (first + max == sum) return new Tuple<int, int>(i, list.IndexOf(max));

        if (first + max < sum) continue;

        for (int j = i+1; j < list.Count; j++)
        {
            int second = list[j];
            if (sum == first + second)
            {
                return new Tuple<int, int>(i, j);
            }
        }
    }
    return null;
}

答案 8 :(得分:1)

这是通过所有4项测试的代码。然而,关于这个问题的abuncha问题令人感兴趣。基本测试:遍历列表,对于列表中的每个数字,遍历列表并找到它的对,即加在一起时与目标值相等的那一对。所以它是O(n ** 2)算法。第四次测试将其烧毁。这里有一个很大的提示,你只需要返回第一个匹配对。所以,要解决:

  • 双重遍历列表并返回解决方案
  • 空列表的特例
  • 没有找到解决方案的特例
  • 输入的特殊情况,当doubled等于目标时:它们必须具有不同的索引。例如:({5,1,3},10)5 + 5 = 10,但是,必须有第二个5,所以这个失败,其中({5,1,3,5},10)成功返回(0 ,3)
  • 因此,为了将算法推向O(n),我们可以记录我们已经找到的#s,因为我们只需要保留每个#的第一次出现。但是,我们需要灵活,快速的数据结构来实现它。数组失败是因为我们不知道它在编译时的大小。我试过List。所以你有1000万个,它保存第一个列表[0] = 1,并收费。接下来是2,2 + 1!= 10,将2添加到列表中,继续。作品。
  • 直到您输入1000万个连续的整数,并且列表很大。所以切换到Dictionary。现在它通过了所有4项测试。

因此,通过输入列表排序,对于每个项目,在字典中搜索其对。如果没有,请在字典中搜索此项目,如果没有,请添加它。当你在字典中找到它的对时,设置你的回报然后去。

public class Item
{
    public Item(int _val, int _loc) {
        val = _val;
        loc = _loc;
    }
    public int val;
    public int loc;
}
class TwoSum
{
    public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
    {
        Tuple<int, int> result = null;
        Dictionary<int, Item> dictionary = new Dictionary<int, Item>();
        int index = 0; 
        bool done = false;

        do
        {
            int curr = list[index];
            int pair = sum - list[index];

            if (dictionary.ContainsKey(pair))
            {
                result = new Tuple<int, int>(index, dictionary[pair].loc);
                done = true;
            }
            else
            {
                if (! dictionary.ContainsKey(curr))
                {
                    Item found1 = new Item(curr, index);
                    dictionary.Add(curr, found1);
                }
            }
            index++;
        }
        while (index < list.Count && !done);
        return result;
    }

答案 9 :(得分:0)

更简单的方法是:

public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
    for (int i = 0; i < list.Count; i++)
    {
      // subtract the item to the sum to find the difference
        int diff = sum - list[i];

      // if that number exist in that list find its index
        if (list.Contains(diff))
        {
            return Tuple.Create(i, list.IndexOf(diff));
        }
    }

    return null;
} 

这样你就不需要事先查询整个列表,但仍然是75%。

答案 10 :(得分:0)

int[] arr = new int[] { 1, 0, 2, 3, 4, 3 };

    for (int i = 0; i < arr.Length; i++)
    {
        var requiredElements = arr.Select((item, index) => new { index, item }).Where(ind => ind.item.Equals(4 - arr[i])).ToList();

        if (requiredElements.Count > 0)
        {
            foreach (var disp in requiredElements)

                Console.WriteLine("Indexes are " + i.ToString() + ":" + disp.index);  
        }
        break;
    }

}

//其中4是目标 - ind.item.Equals(4 - arr [i])

答案 11 :(得分:-2)

public static Tuple FindTwoSum(IList list,int sum)         {

public String getCookiesForHttpResult(SampleResult sampleResult) {

     if (sampleResult instanceof HTTPSampleResult) {

         HTTPSampleResult httpSampleResult = (HTTPSampleResult) sampleResult;
         return httpSampleResult.getCookies();
     }

     // not HTTP result
     return null;
}

}

这将有效