Here we have two different algorithms to solve the problem.
Solution One:
Do an in-place merge sort on the array A;
Loop through each item A[i], use a binary search to check if K-A[i] is in the array;
If found, return the pair (A[i], K-A[i]);
If not found, return the null;
Time Complexity: O ( n * log(n) )
Space Complexity: O ( 1 )
Solution Two:
Allocate the array of size K;
Find the first element in the array A[s] that is less than K, and mark m[A[s] to 1
Loop through each remaining item A[i], check to see if m[K-A(i)] is 1
If m[K-A(i)] is 1, return the pair (A[i], K-A[i]);
If not found, return the null in the end.
Time Complexity: O ( n )
Space Complexity: O ( K )
The code is in Scala.
/**
*
* Problem: Given a number K, and an array of positive integers A, find two integers in the array which sum to K.
*/
object FindPairSumToK {
/*
* Solution One:
* Do an in-place merge sort on the array A;
* Loop through each item A[i], use a binary search to check if K-A[i] is in the array;
* If found, return the pair (A[i], K-A[i]);
* If not found, return the null;
*
* Time Complexity: O ( n * log(n) )
* Space Complexity: O ( 1 )
*/
def findPairSumToKwithSort(A: Array[Int], K: Int) : (Int, Int) = {
mergeSort(A, 0, A.length-1);
for(i <- 0 until A.length){
var t : Int = K - A(i);
if (t>0) {
var idx : Int = binarySearch(A, t);
if (idx>=0) {
return (A(i), A(idx));
}
}
}
return null;
}
/*
* Solution Two:
*
* Allocate the array of size K;
* Find the first element in the array A[s] that is less than K, and mark m[A[s] to 1
* Loop through each remaining item A[i], check to see if m[K-A(i)] is 1
* If m[K-A(i)] is 1, return the pair (A[i], K-A[i]);
* If not found, return the null in the end.
*
* Time Complexity: O ( n )
* Space Complexity: O ( K )
*
*/
def findPairSumToKwithDynamicProgramming(A: Array[Int], K: Int) : (Int, Int) = {
var m: Array[Int] = new Array[Int](K);
var s : Int = 0;
while (s<A.length && A(s)>=K) {
s = s + 1;
}
m(A(s)) = 1;
for(i <- s until A.length){
var target : Int = K - A(i);
if (target>=0 && m(target) ==1) {
return (A(i), target);
}
}
return null;
}
def reverse(a: Array[Int]): Unit = {
if (a.length<=1) return;
var i : Int = 0;
var j : Int = a.length-1;
while (i<j) {
a(i) = a(i) + a(j);
a(j) = a(i) - a(j);
a(i) = a(i) - a(j);
i=i+1;
j=j-1;
}
}
def binarySearch(A: Array[Int], target : Int) : Int = {
var low : Int = 0;
var high: Int = A.length-1;
while (low<high) {
var mid = (low + high) / 2;
if (target==A(mid))
return mid;
else if (target<A(mid))
high = mid-1;
else
low = mid+1;
}
return -1;
}
def mergeSort(a : Array[Int] ) : Unit = {
mergeSort(a, 0, a.length-1);
}
def mergeSort(A: Array[Int], low: Int, high: Int) : Unit = {
if (low >= high) {
return;
}
var mid = (low + high) / 2;
mergeSort(A, low, mid);
mergeSort(A, mid + 1, high);
merge(A, low, mid, high);
}
def merge(a: Array[Int], Low: Int, Mid: Int, High : Int) : Unit = {
var low = Low;
var mid = Mid;
var high = High;
var i : Int = mid;
var j : Int = mid + 1;
while ((low <= i) && (j <= high)) {
if (a(low) < a(j)) {
low = low+1;
} else {
// shift from j to low
var t = a(j);
for (k <- j-1 to (low, -1) ) {
a(k+1) = a(k);
}
a(low) = t;
low = low + 1;
i = i+1;
j = j+1;
}
}
}
def print(a: Array[Int]): Unit = {
println(a.mkString(" "))
}
def main(args: Array[String]) {
val a = Array( 2, 5, 6, 1, 2, 3, 8, 16, 27, 23, 9, 17, 12, 14, 9, 11);
var p = findPairSumToKwithSort(a, 19);
println("p=" + p);
p = findPairSumToKwithSort(a, 99);
println("p=" + p);
val aa = Array( 2, 5, 6, 1, 2, 3, 8, 16, 27, 23, 9, 17, 12, 14, 9, 11);
p = findPairSumToKwithDynamicProgramming(aa, 19);
println("p=" + p);
p = findPairSumToKwithDynamicProgramming(aa, 99);
println("p=" + p);
}
}
Enjoy the journey.