記一道面試題


題目是這樣的,已知一個整數數列(這里應該說的是正整數數列)和一個給定的sum值,從這個整數數列中,找出兩個整數的和剛好等於sum值,將這個數列中所有這種可能的組合進行輸出。

例如:有一個整數數列{3,4,2,7,5,2,4},sum=6,

那么這樣的組合就有:

第二項和第三項的和,即<2,3>;

第二項和第六項的和,即<2,6>;

第三項和第七項的和,即<3,7>;

以此類推…

 

當時我的解答是這樣,比較笨哈:

 

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

namespace ConsoleApplication16
{
class Program
{
static void Main(string[] args)
{
int[] testArray = { 3, 4, 2, 7, 5, 2, 4 };
Console.WriteLine(GetNumCombinations(testArray,6));
}

public static string GetNumCombinations(int[] arrayInt, int sum)
{
List<int> firstNums = new List<int>();
List<int> secondNums = new List<int>();

for (int i = 0; i < arrayInt.Length-1; i++)
{
for (int j = i+1; j < arrayInt.Length; j++)
{
if (arrayInt[i]+arrayInt[j]==sum)
{
firstNums.Add(i+1);
secondNums.Add(j + 1);
}
}
}

StringBuilder sb = new StringBuilder();

for (int i = 0; i < firstNums.Count; i++)
{
sb.Append(String.Format("<{0},{1}>",firstNums[i],secondNums[i]));
}

return sb.ToString();
}
}
}

 

這里有兩個問題,第一個問題就是采用List來保存配對的元素。List的內部順序是不穩定的,也就是說,你先Add進去的元素並不一定會在后Add進去的元素前面,所以,有可能會造成配對的信息錯誤。(這個問題其實我沒考證過,是那個面試官這么解釋的,大致意思我猜想就是這樣)所以應該自定義一個數據結構進行保存。

 

還有一個問題就是算法的效率問題了,具體差在哪?一看就懂得哈!

面試官給了我一個方案,先對數列進行一個從小到大的排序,找sum,和sum/2在數列中的位置,然后再循環查找。

 

回來后總結了一下,我想他的大致意思應該是這樣的:

繼續拿上面得例子演示,先將數列進行排序。

 

2,2,3,4,4,5,7

 

當然,順序亂了,之前的序列值肯定也不對了,所以需要多增加一個數組來維護它的序列值,就假如它排序后的序列值如下:

 

2,2,3,4,4,5,7

3,6,1,2,7,5,4(這一行是序列值)

 

然后找到sum和sum/2在該序列中的位置,sum=6,sum/2=3:

 

2,2,3,(3),4,4,5,(6),7

 

相信大部分人應該看出名堂了吧,想要兩個數的和相加等於6,那么這兩個數必定有一個小於3,另一個大於3,不可能有兩個數都大於3的數相加小於等於6的,同理,也不可能有兩個數都小於3的數相加大於等於6的。

 

在取數據進行相加的時候,設一個變量x從最小值到中間值,一個變量y從最大值到中間值:

 

→x                ←y

2,2,3,(3),4,4,5,(6),7

 

如果兩數相加比sum大,那么最大值y肯定更小,如果兩數相加比sum小,那么最小值x需要更大,直到x與y到中間值為止。

 

代碼重新整理如下(咱就不考慮排序的效率了哈,也沒有很好的容錯性,應該會有各種BUG哈,呵呵!)

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

namespace ConsoleApplication17
{
//保存配對信息
struct NumCombin
{
public int x;
public int y;

public override string ToString()
{
return String.Format("<{0},{1}>", x, y);
}
}

class Program
{
public static NumCombin[] GetNumCombinations(int[] arrayInt, int sum)
{
List<NumCombin> numCombinList = new List<NumCombin>();

//創建一個數組維護排序順序
int[] arrayOrder = new int[arrayInt.Length];
for (int i = 0; i < arrayOrder.Length; i++)
{
arrayOrder[i] = i + 1;
}

//一個簡單的冒泡,進行從小到大的排序
for (int i = 0; i < arrayInt.Length; i++)
{
bool isChange = false;

for (int j = 0; j < arrayInt.Length-1-i; j++)
{
if (arrayInt[j]>arrayInt[j+1])
{
int temp = arrayInt[j];
arrayInt[j] = arrayInt[j + 1];
arrayInt[j + 1] = temp;

temp = arrayOrder[j];
arrayOrder[j] = arrayOrder[j + 1];
arrayOrder[j + 1] = temp;

isChange = true;
}
}

if (!isChange)
{
break;
}
}

int maxCount=-1, halfCount=-1;

for (int i = 0; i < arrayInt.Length; i++)
{
if (arrayInt[i]>sum)
{
maxCount = i;
break;
}
}

if (maxCount==-1)
{
maxCount = arrayInt.Length;
}

for (int i = 0; i < arrayInt.Length; i++)
{
if (arrayInt[i]>sum/2)
{
halfCount = i;
break;
}
}

//如果這個數列最大的數都沒有達到sum值的一半,
//那么肯定不會存在兩個數相加為sum的值
if (halfCount==-1)
{
return null;
}

for (int i = 0; i < halfCount; i++)
{
for (int j = maxCount; j >= halfCount; j--)
{
if (arrayInt[i] + arrayInt[j] > sum)
{
maxCount--;

}
else if (arrayInt[i] + arrayInt[j] < sum)
{
break;
}
else
{
NumCombin numCombin = new NumCombin() { x = arrayOrder[i], y = arrayOrder[j] };
numCombinList.Add(numCombin);
}
}
}

return numCombinList.ToArray();
}

static void Main(string[] args)
{
NumCombin[] test = GetNumCombinations(new int[] { 3, 4, 2, 7, 5, 2, 4 },6);

foreach (var item in test)
{
Console.WriteLine(item);
}

}
}
}

 

 

 

代碼寫得有點拙劣,望廣大博友批評指導!希望有人能提出更好的方案哈!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM