从数组中拾取两个数字,使得总和为常量

时间:2014-01-14 15:41:46

标签: c# algorithm

我遇到了一个算法问题。假设我收到了一个信用卡,并希望从本地商店购买两件商品。我想买两件相当于信用额度的物品。输入数据有三行。

第一行是信用,第二行是商品的总金额,第三行是所有商品的价格。

样本数据1:

200
7
150 24 79 50 88 345 3

这意味着我有200美元购买两件商品,共有7件商品。我应该将第1项和第4项作为200=150+50

购买

样本数据2:

8
8
2 1 9 4 4 56 90 3

这表明我有8美元可以从共8篇文章中挑选两件商品。答案是第4项和第5项,因为8=4+4

我的想法是先创建数组,然后拿起任何项目说项目x。创建另一个数组说"保持"从原始数组中删除x。

从信用证中减去x的价格以获得剩余,并检查"是否保留"包含残余。

这是我在C#中的代码。

        // Read lines from input file and create array price
        foreach (string s in price)
        {
            int x = Int32.Parse(s);
            string y = (credit - x).ToString();

            index1 = Array.IndexOf(price, s) ;
            index2 = Array.IndexOf(price, y) ;
            remain = price.ToList();
            remain.RemoveAt(index1);//remove an element
            if (remain.Contains(y))
            {
                break;
            }
        }
        // return something....

我的两个问题:

  1. 复杂程度如何?我认为是O(n2)。
  2. 对算法的任何改进?当我使用样本2时,我无法获得正确的索引。因为有两个" 4"在数组中,它始终返回第一个索引,因为IndexOf(String)报告此实例中第一次出现的指定字符串的从零开始的索引。

5 个答案:

答案 0 :(得分:4)

您可以在O(nlogn)时间内对数组进行简单排序。然后,对于每个元素A[i],在S-A[i]时间内再次对O(nlogn)进行二分搜索。

编辑:正如Heuster所指出的,你可以通过使用两个指针(一个从头开始,另一个从头到尾)在线性时间内解决排序数组上的2-SUM问题。

答案 1 :(得分:2)

创建HashSet<int>价格。然后顺序完成它。像:

HashSet<int> items = new HashSet<int>(itemsList);

int price1 = -1;
int price2 = -1;
foreach (int price in items)
{
    int otherPrice = 200 - price;
    if (items.Contains(otherPrice))
    {
        // found a match.
        price1 = price;
        price2 = otherPrice;
        break;
    }
}
if (price2 != -1)
{
    // found a match.
    // price1 and price2 contain the values that add up to your target.
    // now remove the items from the HashSet
    items.Remove(price1);
    items.Remove(price2);
}

这是O(n)来创建HashSet。由于HashSet中的查找为O(1),因此foreach循环为O(n)。

答案 2 :(得分:1)

这个问题叫做2-sum。例如,参见http://coderevisited.com/2-sum-problem/

答案 3 :(得分:0)

这是O(N)时间复杂度和O(N)空间的算法: -

1. Put all numbers in hash table.
2. for each number Arr[i] find Sum - Arr[i] in hash table in O(1)
3. If found then (Arr[i],Sum-Arr[i]) are your pair that add up to Sum

注意: - 只有失败的情况可能是当Arr [i] = Sum / 2然后你可以得到误报但你总是可以检查O中数组中是否有两个Sum / 2 (N)

答案 4 :(得分:0)

我知道我发布这是一年半之后,但我碰巧遇到了这个问题,并希望添加输入。

如果存在解决方案,那么您知道解决方案中的两个值都必须小于目标总和。

  1. 在值数组中执行二进制搜索,搜索目标总和(可能存在也可能不存在)。

  2. 二进制搜索将以查找总和或最小值小于sum结束。这是使用前面提到的解决方案在数组中搜索时的起始值。高于新起始值的任何值都不能在解决方案中,因为它超过了目标值。

    1. 此时,您已在log(n)时间内消除了一大块数据,否则将在O(n)时间内消除。
  3. 同样,这是一个优化,如果数据集需要它,可能只值得实现。