A related Java question got me curios.
All unique combinations (not permutations) of 3 values that sum to a target from a list of integers.
Values can duplicate in the list but are only used once.
By sorting the input the evaluation is able to take shortcuts.
Feedback on both code and speed please.
Assume all input and sum >= 0.
public static List<List<int>> FindThreeSum(List<int> input, int sum = 24)
{
//cannot have default on a list to my knowledge
if(input.Count < 3)
{
input = new List<int> { 8, 12, 6, 18, 4, 3, 8, 1, 6, 3, 8, 9, 0 };
//in real life throw an error
}
List<int> sortedInput = input.OrderBy(x => x).ToList();
Debug.WriteLine(string.Join(", ", sortedInput));
int sortedCount = sortedInput.Count;
int maxInput = sortedInput[sortedCount - 1];
List<List<int>> findSum = new List<List<int>>();
if (3 * (long)maxInput < (long)sum || sortedInput[0] < 0 || sum < 0 || 3 * sortedInput[0] > sum)
{
return findSum;
}
int sumSoFar;
int sumI = int.MaxValue;
int sumJ = 0;
int sumK = 0;
for (int i = 0; i < sortedCount - 2; i++)
{
if(sortedInput[i] == sumI)
{
continue;
}
sumI = sortedInput[i];
if(3 * sumI > sum)
{
break; //sumSoFar is only going to get bigger
}
for (int j = i + 1; j < sortedCount - 1; j++)
{
if (sortedInput[j] == sumJ)
{
continue;
}
sumJ = sortedInput[j];
sumSoFar = sumI + sumJ;
if (sumSoFar + sumJ > sum)
{
break;
}
else if(sumSoFar + maxInput < sum)
{
continue;
}
for (int k = j + 1; k < sortedCount; k++)
{
if (sortedInput[k] == sumK)
{
continue;
}
sumK = sortedInput[k];
sumSoFar = sumI + sumJ + sumK;
if (sumSoFar > sum)
{
break;
}
else if(sumSoFar == sum)
{
findSum.Add(new List<int> { sumI, sumJ, sumK });
Debug.WriteLine($"{sumI} {sumJ} {sumK}");
}
}
}
}
Debug.WriteLine("daDone");
return findSum;
}