All possible LCS(Longest Common Subsequence) of two strings - algorithm

We can find the LCS(Longest Common Subsequence) of two strings with DP(Dynamic Programming). By keeping track with DP Table we can get the LCS. But if there exists more than one LCS how can we get all of them?
Example:
string1 : bcab
string2 : abc
Here both "ab" and "bc" are LCS.

Here is a working java solution. For explanation you can see my answer
How to print all possible solutions for Longest Common subsequence
static int arr[][];
static void lcs(String s1, String s2) {
for (int i = 1; i <= s1.length(); i++) {
for (int j = 1; j <= s2.length(); j++) {
if (s1.charAt(i - 1) == s2.charAt(j - 1))
arr[i][j] = arr[i - 1][j - 1] + 1;
else
arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]);
}
}
}
static Set<String> lcs(String s1, String s2, int len1, int len2) {
if (len1 == 0 || len2 == 0) {
Set<String> set = new HashSet<String>();
set.add("");
return set;
}
if (s1.charAt(len1 - 1) == s2.charAt(len2 - 1)) {
Set<String> set = lcs(s1, s2, len1 - 1, len2 - 1);
Set<String> set1 = new HashSet<>();
for (String temp : set) {
temp = temp + s1.charAt(len1 - 1);
set1.add(temp);
}
return set1;
} else {
Set<String> set = new HashSet<>();
Set<String> set1 = new HashSet<>();
if (arr[len1 - 1][len2] >= arr[len1][len2 - 1]) {
set = lcs(s1, s2, len1 - 1, len2);
}
if (arr[len1][len2 - 1] >= arr[len1 - 1][len2]) {
set1 = lcs(s1, s2, len1, len2 - 1);
}
for (String temp : set) {
set1.add(temp);
}
//System.out.println("In lcs" + set1);
return set1;
}
}
public static void main(String[] args) {
String s1 = "bcab";
String s2 = "abc";
arr = new int[s1.length() + 1][s2.length() + 1];
lcs(s1, s2);
System.out.println(lcs(s1, s2, s1.length(), s2.length()));
}

When you calculate a cell in the DP table, keep a backpointer to the previous cell used for that result. If there is a tie, keep multiple backpointers for all of the tied results. Then retrace the path using the backpointers, following all paths.

Here is a commented Java program to find all possible lcs.
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class LongestCommonSubsequence {
public static int[][] LCSmatrix(String X, String Y) {
//we ignore the top most row and left most column in this matrix
//so we add 1 and create a matrix with appropriate row and column size
int m = X.length() + 1, n = Y.length() + 1;
int[][] c = new int[m][n];
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
//since we added 1 to row size and column size,
// we substract 1 from i,j to find the char at that index
if (X.charAt(i - 1) == Y.charAt(j - 1)) {
c[i][j] = c[i - 1][j - 1] + 1;
} else if (c[i - 1][j] >= c[i][j - 1]) {
c[i][j] = c[i - 1][j];
} else {
c[i][j] = c[i][j - 1];
}
}
}
printMatrix(c);
return c;
}
public static void printMatrix(int[][] grid) {
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
System.out.print(grid[r][c] + " ");
}
System.out.println();
}
}
public static void allLCS(int[][] c, String X, String Y, int i, int j, Set<String> setLCS, String s) {
//return when either of the string length is 0
if (i == 0 || j == 0) {
setLCS.add(s);
return;
}
//if last characters are equal, they belong in lcs
if (X.charAt(i - 1) == Y.charAt(j - 1)) {
//prepend the char to lcs since, we are going backwards
s = X.charAt(i - 1) + s;
//continue finding lcs in substrings X.substring(0,i-1) and Y.substring(0,j-1)
allLCS(c, X, Y, i - 1, j - 1, setLCS, s);
} // if there is a tie in matrix cells, we backtrack in both ways,
// else one way, which ever is greater
else if (c[i - 1][j] == c[i][j - 1]) {
//continue finding lcs in substring X.substring(0,i-1)
allLCS(c, X, Y, i - 1, j, setLCS, s);
//continue finding lcs in substring Y.substring(0,j-1)
allLCS(c, X, Y, i, j - 1, setLCS, s);
} else if (c[i - 1][j] > c[i][j - 1]) {
allLCS(c, X, Y, i - 1, j, setLCS, s);
} else {
allLCS(c, X, Y, i, j - 1, setLCS, s);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println(" Enter String X and Y : ");
String X = sc.next();
String Y = sc.next();
sc.close();
Set<String> set = new HashSet<String>();
allLCS(LCSmatrix(X, Y), X, Y, X.length(), Y.length(), set, "");
System.out.println(set.toString());
}
}

Related

Return a subset of integers that maximizes its (mean - median)

A set of integers is given as input. You have to return the subset of that set so that the mean - median is maximum for that subset.
Example 1
Input
{1,2,3,4}
Output
{1,2,4}
Example 2
Input
{1,2,2,3,3}
Output
{2,2,3}
package subsetMean_Median;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MySolution {
public static void main(String[] args) {
int[] arr=
{2,3,2,1,3};
// {1,3,2,4};
Arrays.sort(arr);
int[] outp=meanMedian(arr);
for(int e:outp) {
System.out.print(e+"\t");
}
}
protected static int[] meanMedian(int[] arr) {
double median=findMedian(arr);
double mean=findMean(arr);
double diff=median-mean;
int MAXINDEX=0;
int n=arr.length;
double sets=(1<<n);
System.out.println("sets:"+sets);
for(int i=1;i<=sets;i++) {
int[] subset=findSubset(i,arr);
mean=findMean(subset);
median=findMedian(subset);
if(mean -median>diff) {
diff=mean-median;MAXINDEX=i;
}
}
System.out.println("mean: "+mean+"\tmedian: "+median+"\tdiff: "+diff);
return findSubset(MAXINDEX,arr);
}
protected static int[] findSubset(int counter, int[] arr) {
int n=arr.length;
List<Integer> ls=new ArrayList<Integer>();
for(int j=0;j<n;j++) {
if((counter & (1<<j))>0) {
ls.add(arr[j]);
}
}
int[] output= new int[ls.size()];
for(int j=0;j<ls.size();j++) {
output[j]=ls.get(j);
}
return output;
}
protected static double findMean(int[] arr) {
int n=arr.length;
double sum=0;
if(n==0) return 0;
for(int i=0;i<n;i++)
sum +=arr[i];
return (sum/n);
}
protected static double findMedian(int[] arr) {
int n=arr.length;
if(n%2==1)
return arr[(n/2)];
else if(n>=2)
return 0.5*(arr[((n-2)/2)]+arr[n/2]);
else return 0;
}
}
For every possible median:
lllllmrrrrr
Sort both parts L and R, then start choosing in pair lr maximal elements from both parts and with addition of every next element recompute mean, store arrangement with the best difference. Then the same for minimal elements.
There are about N possible medians, sorting takes O(N*lgN), on every iteration you need to compute up to N means, you can do it in O(N). So, overall complexity is O(N^3*LgN), but most likely you can avoid sorting on every iteration, instead sort whole array only once and update parts in O(1) on every iteration. With such an improvements it is O(N^2).
The most important thing in this problem is to find the Subset.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MeanMedian {
public static void main(String[] args) {
int[] arr = { 1, 2, 3 };// { 1, 2, 2, 3, 3 };// { 1, 2, 3, 4 };
returnMaxMeanMedian(arr);
}
private static void returnMaxMeanMedian(int[] arr) {
double max = -999.9;
List<Integer[]> subArr = subSet(arr);
Integer[] maxArr = new Integer[1];
for (Integer[] sub : subArr) {
double newMax = calcDiff(sub);
if (max <= newMax) {
max = newMax;
maxArr = sub;
}
}
System.out.println(Arrays.toString(maxArr));
}
private static double calcDiff(Integer[] sub) {
// calc. mean
double sum = 0;
for (int i = 0; i < sub.length; i++) {
sum += sub[i];
}
sum = sum / sub.length;
// calc. median
double median = 0;
if (sub.length % 2 == 0)
median = (double) (sub[(sub.length / 2) - 1] + sub[sub.length / 2]) / 2;
else
median = sub[sub.length / 2];
double diff = sum - median;
return diff;
}
private static List<Integer[]> subSet(int[] arr) {
List<Integer[]> subArr = new ArrayList<Integer[]>();
int n = arr.length;
// Run a loop until 2^n
// subsets one by one
for (int i = 0; i < (1 << n); i++) {
String subSet = "";
// Print current subset
for (int j = 0; j < n; j++)
if ((i & (1 << j)) > 0)
subSet += arr[j] + " ";
subArr.add(convertToInt(subSet.trim().split(" ")));
}
return subArr;
}
private static Integer[] convertToInt(String[] arr) {
if (arr[0] == "")
return new Integer[] { 0 };
Integer[] intArr = new Integer[arr.length];
for (int i = 0; i < arr.length; i++) {
intArr[i] = Integer.parseInt(arr[i].trim());
}
return intArr;
}
}
Sort the list in O(n log n).
Deleting any element to the left of the median (center element or pair) has the same effect on the median, but affect the mean differently. Ditto for elements to the right.
That means that if anything will improve (mean - median), one of these will improve it the most:
the smallest element in the array
the smallest element to the right of the median
one of the element(s) that comprises the median
I.e., for each possible new median, how can we achieve the largest mean?
Repeatedly check these 3-4 for improving mean-median, deleting whatever improves the most. Each operation is O(1), as is recalculating the mean and median. You have to do this at most O(n) times.
The running time is O(n log n) if the list is unsorted, otherwise O(n).
Is this question only for a positive sequence of numbers? If yes, there's this efficient piece of code I wrote:
import java.util.Scanner;
public class MeanMedian {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int i;
int j;
int k;
int in_length;
int mid_loc;
int sum_arr;
float median = 0.0f;
float mean = 0.0f;
float delta = 0.0f;
float incremental_delta = 0.0f;
float MEDIAN_FOR_MAX_DELTA = 0.0f;
float MEAN_FOR_MAX_DELTA = 0.0f;
float MAX_DELTA = -1.0f;
int MAX_SEQ_LENGTH = 0;
System.out.print("Enter the length of input: ");
in_length = sc.nextInt();
int in_arr[]= new int [in_length+1];
int out_arr[] = new int [in_length+1]; //This is the maximum size of the output array.
int MAX_DELTA_ARR[] = new int [in_length+1];
// STAGE-1: Accept the input sequence
for (i = 1; i <= in_length; i++) {
System.out.print("Enter the input #" + i + ": ");
in_arr[i] = sc.nextInt();
}
// STAGE-1 completed.
// STAGE-2: Sort the array (Bubble sort in Ascending order)
for (j = 1; j < in_length; j++) {
for (i = in_length; i > j; i--) {
if (in_arr[i-1] > in_arr[i]) {
k = in_arr[i];
in_arr[i] = in_arr[i-1];
in_arr[i-1] = k;
}
}
}
// STAGE-2 completed.
// STAGE-3: Compute Max Delta
MAX_DELTA = -99999; //Store as large -ve number as float data type can hold.
for (i = in_length; i > 2; i--) {
// STAGE-3a: Optional - Clear the out_arr[]
for (j = 1; j <= in_length; j++) {
out_arr [j] = 0;
}
// STAGE-3a completed.
// STAGE-3b: Determine the index of the median for the sequence of length i
if (i % 2 == 1) {
mid_loc = (i + 1)/2;
}
else {
mid_loc = (i / 2) + 1;
}
// STAGE-3b completed.
// STAGE-3c: Create the selection that gives the min median and max mean.
// STAGE-3c1: Create left side of mid point.
for (j = mid_loc; j > 0; j--) {
out_arr[j] = in_arr[j];
}
// STAGE-3c1 completed.
// STAGE-3c2: Create right side of mid point.
k = in_length;
for (j = i; j > mid_loc; j--) {
out_arr[j] = in_arr[k];
k = k - 1;
}
// STAGE-3c2 completed.
// STAGE-3c3: Do the SHIFT TEST.
//for (; k <= mid_loc + in_length - i; k++) {
for (k = mid_loc + 1; k <= mid_loc + in_length - i; k++) {
if (i % 2 == 1) {
incremental_delta = ((float)in_arr[k] - (float)out_arr[1])/i - ((float)in_arr[k] - (float)out_arr[mid_loc]);
}
else {
incremental_delta = ((float)in_arr[k] - (float)out_arr[1])/i - (((float)in_arr[k] - (float)out_arr[mid_loc]/2));
}
if (incremental_delta >= 0 ) {
//Insert this new element
for(j = 1; j < mid_loc; j++) {
out_arr[j] = out_arr[j+1];
}
out_arr[mid_loc] = in_arr[k];
}
}
// STAGE-3c3 completed.
// STAGE-3d: Find the median of the present sequence.
if(i % 2 == 1) {
median = out_arr[mid_loc];
}
else {
median = ((float)out_arr[mid_loc] + (float)out_arr[mid_loc - 1])/2;
}
// STAGE-3d completed.
// STAGE-3e: Find the mean of the present sequence.
sum_arr = 0;
for(j=1; j <= i ; j++) {
sum_arr = sum_arr + out_arr[j];
}
mean = (float)sum_arr / i;
// STAGE-3e completed.
// STAGE-3f: Find the delta for the present sequence and compare with previous MAX_DELTA. Store the result.
delta = mean - median;
if(delta > MAX_DELTA) {
MAX_DELTA = delta;
MEAN_FOR_MAX_DELTA = mean;
MEDIAN_FOR_MAX_DELTA = median;
MAX_SEQ_LENGTH = i;
for (j = 1; j <= MAX_SEQ_LENGTH; j++) {
MAX_DELTA_ARR[j] = out_arr[j];
}
}
// STAGE-3f completed.
}
// STAGE-4: Print the result.
System.out.println("--- RESULT ---");
System.out.print("The given input sequence is: ");
System.out.print("{ ");
for(i=1; i <= in_length; i++) {
System.out.print(in_arr[i]);
System.out.print(" ");
}
System.out.print("}");
System.out.println("");
System.out.print("The sequence with maximum difference between mean and median is: ");
System.out.print("{ ");
for(i=1; i <= MAX_SEQ_LENGTH; i++) {
System.out.print(MAX_DELTA_ARR[i]);
System.out.print(" ");
}
System.out.print("}");
System.out.println("");
System.out.println("The mean for this sequence is: " + MEAN_FOR_MAX_DELTA);
System.out.println("The median for this sequence is: " + MEDIAN_FOR_MAX_DELTA);
System.out.println("The maximum difference between mean and median for this sequence is: " + MAX_DELTA);
}
}
This code has order O(n) (if we ignore the necessity to sort the input array).
In case, -ve inputs are also expected - the only way out is by evaluating each subset. The downside to this approach is that the algorithm has exponential order: O(2^n).
As a compromise you could use both types of algorithm in your code and switch between the two by evaluating the input sequence. By the way, where did you come across this question?
from itertools import combinations
[Verfication of the code][1]
# function to generate all subsets possible, there will be 2^n - 1 subsets(combinations)
def subsets(arr):
temp = []
for i in range(1, len(arr)+1):
comb = combinations(arr, i)
for j in comb:
temp.append(j)
return temp
# function to calculate median
def median(arr):
mid = len(arr)//2
if(len(arr)%2==0):
median = (arr[mid] + arr[mid-1])/2
else:`
median = arr[mid]
return median
# function to calculate median
def mean(arr):
temp = 0
for i in arr:
temp = temp + i
return temp/len(arr)
# function to solve given problem
def meanMedian(arr):
sets = subsets(arr)
max_value = 0
for i in sets:
mean_median = mean(i)-median(i)
if(mean_median>max_value):
max_value = mean_median
needed_set = i
return needed_set
[1]: https://i.stack.imgur.com/Mx4pc.png
So I tried a little on the problem and here is a code that might help you. Its written in a way that should be easy to read, and if not, do let me know. Maybe you need to take array input from the user as I have taken a fixed array. That shouldn't be much of a problem I am sure.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class MeanMinusMedian
{
private static float mean = 0;
private static float median = 0;
private static float meanMinusMedian = 0;
private static List<Integer> meanMinusMedianList = null;
private static void formMeanMinusMedianArr(int data[], int sumOfData)
{
findMean(data, sumOfData);
findMedian(data);
if ((mean - median) > meanMinusMedian) {
meanMinusMedian = mean - median;
meanMinusMedianList = new ArrayList<Integer>();
Arrays.stream(data)
.forEach(e->meanMinusMedianList.add(e));
}
}
/**
* #param data
*/
private static void findMedian(int[] data) {
int dataLen = data.length;
median = data.length % 2 == 0 ? ((float)data[dataLen / 2] + (float)data[dataLen / 2 - 1]) / 2 : data[dataLen / 2];
}
/**
* #param data
* #param sumOfData
*/
private static void findMean(int[] data, int sumOfData) {
mean = ((float)sumOfData /(float) data.length);
}
/**
*
* #param arr
* #param data
* #param start
* #param end
* #param index
* #param runningVal
*/
private static void combinationUtil(int arr[], int data[], int start, int end, int index, int runningVal) {
// Current combination is ready to be printed, print it
if (index == runningVal) {
formMeanMinusMedianArr(data, Arrays.stream(data) // Step 1
.sum());
return;
}
// replace index with all possible elements. The condition
// "end-i+1 >= r-index" makes sure that including one element
// at index will make a combination with remaining elements
// at remaining positions
for (int i = start; i <= end && end - i + 1 >= runningVal - index; i++) {
data[index] = arr[i];
combinationUtil(arr, data, i + 1, end, index + 1, runningVal);
}
}
/**
*
* #param arr
* #param n
* #param runningVal
*/
private static void printCombination(int arr[], int n, int runningVal) {
int data[] = new int[runningVal];
// Print all combination using temporary array 'data[]'
combinationUtil(arr, data, 0, n - 1, 0, runningVal);
}
public static void main(String[] args) {
int arr[] = { 1, 2, 2, 3, 3 };
int runningVal = 1;//Running value
int len = arr.length;
for (int i = 1; i < arr.length; i++) {
printCombination(arr, len, runningVal + i);
}
System.out.println(meanMinusMedianList);
}
}
Taking reference of answer of Bhaskar13 https://stackoverflow.com/a/59386801/3509609 , I solved it without using the bit shift operators, to add more readability.
package array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class MeanMinusMedianMax {
public static void main(String[] args) {
System.out.println(Arrays.toString(maxDiffrenceSubSet(4, new int[] { 4, 2, 3, 1 })));
System.out.println(Arrays.toString(maxDiffrenceSubSet(4, new int[] { 1, 2, 2, 3, 3 })));
}
public static int[] maxDiffrenceSubSet(int n, int[] input2) {
int totalSubsets = (int) Math.pow(2, n);
Map<Integer, ArrayList<Integer>> subsetsMap = new HashMap<Integer, ArrayList<Integer>>();
Integer maxKey = null;
double maxDiff = 0;
for (int i = 0; i < totalSubsets; i++) {
String binaryString = Integer.toBinaryString(i);
while (binaryString.length() < 4) {
binaryString = "0" + binaryString;
}
char[] currentPick = binaryString.toCharArray();
ArrayList<Integer> currentList = new ArrayList<Integer>();
for (int x = 0; x < currentPick.length; x++) {
if ((currentPick[x]) == '1') {
currentList.add(input2[x]);
}
}
Collections.sort(currentList);
subsetsMap.put(i, currentList);
double mean = findMean(currentList);
double median = findMedian(currentList);
double currentDifference = mean - median;
if (currentDifference > maxDiff) {
maxDiff = currentDifference;
maxKey = i;
}
}
return subsetsMap.get(maxKey).stream().mapToInt(i -> i).toArray();
}
static double findMean(ArrayList<Integer> arr) {
int n = arr.size();
double sum = 0;
if (n == 0)
return 0;
for (int i = 0; i < n; i++)
sum += arr.get(i);
return (sum / n);
}
static double findMedian(ArrayList<Integer> arr) {
int n = arr.size();
if (n % 2 == 1)
return arr.get((n / 2));
else if (n >= 2)
return 0.5 * (arr.get(((n - 2) / 2)) + arr.get(n / 2));
else
return 0;
}
}
class UserMainCode (object):
def meanmedian(cls,ip1,ip2=[]):
s = []
s = ip2
lst = []
final = []
op = []
max_val = 0
diff = 0
for i in range(1,ip1+1):
n=i
lst = list(itertools.combinations(s,n))
final = final +lst
for i in range(len(final)):
men = statistics.mean(final[i])
med = statistics.median(final[i])
diff = men - med
if max_val < diff:
op = final[i]
max_val = diff
return op

Algorithm for Adding/Subtracting numbers to find if number can be made?

I was wondering if there is an efficient premade algorithm for determining if the sum/difference of a group of numbers can equal a different number. Example:
5, 8, 10, 2, using + or -, to equal 9.
5 - 8 = -3 + 10 = 7 + 2 = 9
If there is a preexisting algorithm, what is it called. If not, I can figure out how to program it, though it may not be efficient.
Thank you!
Yeah, this is basically knapsack problem, but it can be computed in pseudopolynomial time using dynamic programming.
I did it few month ago, so maybe this java code can help you, if you want to implement it :
public void solve() {
while (this.isEnd() == false) {
int priceSum = this.getItemsInstance().getTotalPrice()/divide;
int numOfItems = this.getItemsInstance().itemCount();
int maxWeight = this.getItemsInstance().getMaxWeight();
int[][] array = new int[numOfItems + 1][priceSum + 1];
boolean[][] arrayCounted = new boolean[numOfItems + 1][priceSum + 1];
for (int i = 0; i < numOfItems + 1; i++) {
array[i][0] = 0;
arrayCounted[i][0] = true;
}
int max = 0;
int price = 0;
for (int j = 1; j < priceSum + 1; j++) {
for (int i = 1; i < numOfItems + 1; i++) {
int temp = W(i, j, array, arrayCounted);
if (temp <= maxWeight) {
max = temp;
price = j;
}
}
}
}
}
private int W(int i, int c, int[][] array, boolean[][] arrayCounted) {
if (c < 0) {
return MAX_PRICE / divide;
}
if (i == 0) {
if (c == 0) {
return 0;
} else {
return MAX_PRICE / divide;
}
}
if (arrayCounted[i][c]) {
return array[i][c];
}
arrayCounted[i][c] = true;
array[i][c] = Math.min(W(i - 1, c, array, arrayCounted), W(i - 1, c - this.items[i - 1].price/divide, array, arrayCounted) + this.items[i - 1].weight);
return array[i][c];
}
its not an NP problem, if the problem is to find a given number from adding or subtracting each elements of a list/array. if you think about AP. here is a sample code in C++
int Np( int mn, list<int>a, int c )
{
int size = a.size(), rst = 0, maxI = 0;
std::list<int>::iterator it;
while( size > c )
{
a.sort();
maxI += a.back();
a.pop_back();
rst = 0;
for( auto ele : a )
{
rst += ele;
cout << rst << endl;
}
if( (rst - maxI) == mn or (maxI - rst) == mn or (maxI + rst) == mn )
{
return mn;
}
size--;
}
return rst;
}
this should help. i think.
I actually wrote a simple java program, I was not actually aware of knapsack strategies. This is my own solution. Hope this helps
import java.util.ArrayList;
import java.util.List;
public class Puzzle {
public static void main(String[] args) {
int targetNumber = 0;
int min = 2147483647;
int[] numbers = {-10, -30, -20, -50};
//int[] numbers = {0,0,0,0};
//int[] numbers = {7, 2, 10};
//int[] numbers = {1, 2, 3, 4, 5};
//int[] numbers = {1000, 2, 3, 4, 100};
char set[] = {'+', '-'};
min = getNumberClosestToTarget(numbers, set, min, targetNumber);
System.out.println(String.format(" %d is closest to %d", min, targetNumber));
}
private static int getNumberClosestToTarget(int[] numbers, char[] set, int min, int targetNumber) {
List<String> operators = new ArrayList<>();
computeAllOperatorsCombination(set, "", set.length, numbers.length - 1, operators);
for (String operatorString : operators) {
String[] ops = operatorString.split("");
int sum = computeSum(numbers, ops, numbers.length - 1);
min = getClosestToTarget(min, targetNumber, sum);
}
return min;
}
static int computeSum(int[] numbers, String[] operators, int index) {
int result = numbers[index];
if (index == 0) {
return result;
} else {
switch (operators[index - 1]) {
case "+":
return computeSum(numbers, operators, index - 1) + result;
case "-":
return computeSum(numbers, operators, index - 1) - result;
}
return result;
}
}
static void computeAllOperatorsCombination(char set[], String prefix, int n, int k, List<String> result) {
if (k == 0) {
result.add(prefix);
return;
}
for (int i = 0; i < n; i++) {
String newPrefix;
newPrefix = prefix + set[i];
computeAllOperatorsCombination(set, newPrefix, n, k - 1, result);
}
}
private static int getClosestToTarget(int min, int targetNumber, int r) {
int distance = Math.abs(targetNumber - r) < Math.abs(r - targetNumber) ? Math.abs(targetNumber - r) : Math.abs(r - targetNumber);
if (distance < Math.abs(min)) {
min = distance;
if (r < 0) {
min = -distance;
}
}
return min;
}
}

Check if an array element is a sum of two earlier elements using recursion

I was solving practice questions from a book when I stumbled upon this one :
*Describe a recursive algorithm that will check if an array A of
integers contains an integer A[i] that is the sum of two integers
that appear earlier in A, that is, such that
A[i] = A[j] +A[k] for j,k < i.
*
I have been thinking about this for a few hours but haven't been able to come up with a good recursive algorithm.
A recursive solution without any loops (pseudocode):
bool check (A, i, j, k)
if (A[j] + A[k] == A[i])
return true
else
if (k + 1 < j) return check (A, i, j, k + 1)
else if (j + 1 < i) return check (A, i, j + 1, 0)
else if (i + 1 < A.size) return check (A, i + 1, 1, 0)
else return false
The recursive function is called with check(A, 2, 1, 0). To highlight the main part of the algorithm it does not check if the array initially has more than two elements.
Not very efficient but..
search(A, j, k) {
for (int i = 0; i < A.length; i++) {
if (A[i] == A[j] + A[k]) {
return i;
}
}
if (k + 1 == A.length) {
if (j + 1 < A.length) {
return search(A, j + 1, 0);
}
return -1; // not found
}
return search (A, j, k + 1);
}
Start the search with
search(A, 0, 0);
In python. The first function (search is less efficient O(n3)), but it also gives the j and k, the second one is more efficient (O(n2)), but only returns i.
def search(A, i):
for j in xrange(i):
for k in xrange(i):
if A[i] == (A[j] + A[k]):
return i, j, k
if i > 0:
return search(A, i - 1)
def search2(A, i, sums):
if A[i] in sums:
return i
if i == len(A) - 1:
return None
for j in range(i + 1):
sums.add(A[i] + A[j])
return search2(A, i + 1, sums)
if __name__ == '__main__':
print search([1, 4, 3], 2)
print search([1, 3, 4], 2)
print search2([1, 4, 3], 0, set())
print search2([1, 3, 4], 0, set())
It will print:
None
(2, 0, 1)
None
2
/**
* Describe a recursive algorithm that will check if an array A of integers contains
* an integer A[i] that is the sum of two integers that appear earlier in A,
* that is, such that A[i] = A[j]+A[k] for j,k < i.
* #param A - array
* #param i - initial starting index (0)
* #param j - initival value for j (0)
* #param k - initial value for k (0)
* #param n - length of A - 1
* #return - true if combination of previous 2 elements , false otherwise
*/
public boolean checkIfPreviousTwo(int[] A, int i, int j, int k, int n){
if(i >= n) return false;
if(j < i && k < i){
if(A[j] + A[k] == A[i]) return true;
return(
checkIfPreviousTwo(A, i, j + 1, k, n) ||
checkIfPreviousTwo(A, i, j, k + 1, n)
);
}
return checkIfPreviousTwo(A, i + 1, j, k, n);
}
This algorithm should be fairly efficient (well, O(n2)):
import Data.Set (Set, empty, fromList, member, union)
-- Helper function (which does all the work)
hassum' :: (Ord a, Num a) => Set a -> [a] -> [a] -> Bool
-- Parameters:
-- 1. All known sums upto the current element
-- 2. The already handles elements
-- 3. The not yet checked elements
-- If there are no elements left to check, there is no sum
hassum' _ _ [] = False
-- Otherwise...
hassum' sums done (x:xs)
-- Check if the next element is a known sum
| x `member` sums = True
-- Otherwise calculate new possible sums and check the remaining elements
| otherwise = hassum' sums' done' xs
where sums' = sums `union` fromList [x+d | d <- done]
done' = x:done
-- Main function
hassum :: (Ord a, Num a) => [a] -> Bool
hassum as = hassum' empty [] as
I hope you can make sense of it even if you might not know Haskell.
The Java version, it also return the index of i,j,k.
the running time of the worst case is O(N^2)
=1= using recursion
private static void findSum(Object[] nums, long k, int[] ids/* indexes*/) {
// walk from both sides towards center
int l = ids[0];
int r = ids[1];
if (l == r) {
ids[0] = -1;
ids[1] = -1;
return;
}
int sum = (Integer) nums[l] + (Integer) nums[r];
if (sum == k) {
return;
}
if (sum < k) {
ids[0]++;
} else {
ids[1]--;
}
findSum(nums, k, ids);
}
private static int binarySearchPositionIndexOf(List<Integer> list, int l, int r, int k) {
int m = (l + r) / 2;
if (m == l) { // end recursion
return r;
}
int mv = list.get(m);
if (mv == k) {
return m;
}
if (mv < k) {
return binarySearchPositionIndexOf(list, m, r, k);
}
return binarySearchPositionIndexOf(list, l, m, k);
}
private static void check(List<Integer> data, List<Integer> shadow, int i, int[] ids) {
if (i == data.size()) {
ids[0] = -1;
ids[1] = -1;
return;
}
// sort it in
int indexAfterSort = -1;
int v = data.get(i);
if (v >= data.get(i - 1)) {
indexAfterSort = i;
} else if (v <= data.get(0)) {
indexAfterSort = 0;
} else if (data.size() == 3) {
indexAfterSort = i - 1;
} else {
indexAfterSort = binarySearchPositionIndexOf(data, 0, i - 1, data.get(i));
}
if (indexAfterSort != i) {
data.add(indexAfterSort, data.remove(i));
shadow.add(indexAfterSort, shadow.remove(i));
}
// find sum
if (indexAfterSort >= 2) {
List<Integer> next = data.subList(0, indexAfterSort); //[)
ids[0] = 0;
ids[1] = next.size() - 1;
findSum(next.toArray(), data.get(indexAfterSort), ids);
}
// recursion
if (ids[0] == -1 && ids[1] == -1) {
check(data, shadow, i + 1, ids);
return;
}
ids[0] = shadow.get(ids[0]);
ids[1] = shadow.get(ids[1]);
ids[2] = i;
}
public static int[] check(final int[] array) {
List shadow = new LinkedList() {{
for (int i = 0; i < array.length; i++) {
add(i);
}
}};
if (array[0] > array[1]) {
array[0] ^= array[1];
array[1] ^= array[0];
array[0] ^= array[1];
shadow.add(0, shadow.remove(1));
}
int[] resultIndex = new int[3];
resultIndex[0] = -1;
resultIndex[1] = -1;
check(new LinkedList<Integer>() {{
for (int i = 0; i < array.length; i++) {
add(array[i]);
}
}}, shadow, 2, resultIndex);
return resultIndex;
}
Test
#Test(timeout = 10L, expected = Test.None.class)
public void test() {
int[] array = new int[]{4, 10, 15, 2, 7, 1, 20, 25};
int[] backup = array.clone();
int[] result = check(array);
Assert.assertEquals(backup[result[2]], 25);
Assert.assertEquals(result[2], 7);
Assert.assertEquals(backup[result[0]], 10);
Assert.assertEquals(result[0], 1);
Assert.assertEquals(backup[result[1]], 15);
Assert.assertEquals(result[1], 2);
array = new int[]{4, 10, 15, 2, 7, 1, 10, 125};
backup = array.clone();
result = check(array);
Assert.assertEquals(result[0], -1);
Assert.assertEquals(result[1], -1);
}
=2= simple one without recurison:
// running time n + n^2
// O(n^2)
public static int[] check2(final int[] array) {
int[] r = new int[3];
r[0] = -1;
r[1] = -1;
r[2] = -1;
Map<Integer, List<Integer>> map = new HashMap(array.length);
for (int i = 0; i < array.length; i++) {
int v = array[i];
List<Integer> ids = map.get(v);
if (ids == null) {
ids = new LinkedList();
}
ids.add(i);
map.put(v, ids);
}
for (int k = 0; k < array.length; k++) {
int K = array[k];
for (int j = 0; j < array.length; j++) {
int I = K - array[j];
if (map.keySet().contains(I)) {
List<Integer> ids = map.get(I);
for (int i : ids) {
if (i != j) {
r[0] = j;
r[1] = i;
r[2] = k;
return r;
}
}
}
}
}
return r;
}
Test:
int[] array = new int[]{0,8,8};
int[] result = check2(array);
Assert.assertEquals(array[result[2]], 8);
Assert.assertEquals(result[2], 1);
Assert.assertEquals(array[result[0]], 0);
Assert.assertEquals(result[0], 0);
Assert.assertEquals(array[result[1]], 8);
Assert.assertEquals(result[1], 1);

How to find permutation of a given string with its rank?

For example,
rank permutation
0 abc
1 acb
2 bac
3 bca
4 cab
5 cba
So, if one asks give me permutation with rank 4, the answer is cab. Pls give the java code for this program
I made it at a first attempt!! :-)
Really good homework, nice problem, you made my day! Here is a solution in javascript:
function permutation (rank, n, chars)
{
var fact, char_idx, this_char;
if (n == 0)
return "";
char_idx = Math.floor(rank / factorial(n - 1));
this_char = chars.splice(char_idx, 1);
// returns the char with index char_idx and removes it from array
return this_char +
permutation(rank % factorial(n - 1), n - 1, chars);
}
Just call it like permutation(5, 3, ['a', 'b', 'c']) and that's it.
You have to write your own factorial() function - as a homework :-)
Here is a c# version: basic idea is to using factorial to determine the permutation, rather than by trying to get all the permutations (you may refer to my blog # http://codingworkout.blogspot.com/2014/08/kth-permutation.html)
public string GetKthPermutation(string s, int k, int[] factorial)
{
if (k == 1)
{
return s;
}
Assert.IsTrue(k > 1);
int numbeOfPermutationsWithRemainingElements = factorial[s.Length-1];
string permutation = null;
if (k <= numbeOfPermutationsWithRemainingElements)
{
//just find the kthPermutation using remaining elements
permutation = s[0] + this.GetKthPermutation(s.Substring(1), k,
factorial);
return permutation;
}
int quotient = k / numbeOfPermutationsWithRemainingElements;
int remainder = k % numbeOfPermutationsWithRemainingElements;
Assert.IsTrue(quotient > 0);
int indexOfCurrentCharacter = quotient;
if(remainder == 0)
{
indexOfCurrentCharacter -= 1;
}
permutation = s[indexOfCurrentCharacter].ToString();
Assert.IsTrue(indexOfCurrentCharacter > 0);
Assert.IsTrue(indexOfCurrentCharacter < s.Length);
string remainingCharactersString = s.Substring(0, indexOfCurrentCharacter);
if(indexOfCurrentCharacter < (s.Length-1))
{
remainingCharactersString += s.Substring(indexOfCurrentCharacter + 1);
}
if(remainder == 0)
{
k = numbeOfPermutationsWithRemainingElements;
}
else
{
k = remainder;
}
permutation += this.GetKthPermutation(remainingCharactersString, k, factorial);
return permutation;
}
where
public string GetKthPermutation(string s, int k)
{
s.ThrowIfNullOrWhiteSpace("a");
k.Throw("k", ik => ik <= 0);
int[] factorial = new int[s.Length+1];
factorial[0] = 0;
factorial[1] = 1;
for(int i =2;i<=s.Length; i++)
{
factorial[i] = factorial[i - 1] * i;
}
if(k > factorial[s.Length])
{
throw new Exception(string.Format("There will be no '{0}' permuation as the total number of permutations that can be abieved are '{1}'", k, s.Length));
}
string kthPermutation = this.GetKthPermutation(s, k, factorial);
return kthPermutation;
}
Unit Test
[TestMethod]
public void KthPermutationTests()
{
string s1 = "abc";
string[] perms1 = { "abc", "acb", "bac", "bca", "cab", "cba"};
for(int i =1;i<=6;i++)
{
string s = this.GetKthPermutation(s1, i);
Assert.AreEqual(s, perms1[i - 1]);
string ss = this.GetKthPermutation_BruteForce(s1, i);
Assert.AreEqual(ss, s);
}
s1 = "123";
perms1 = new string[] {"123", "132", "213", "231", "312", "321"};
for (int i = 1; i <= 6; i++)
{
string s = this.GetKthPermutation(s1, i);
Assert.AreEqual(s, perms1[i - 1]);
string ss = this.GetKthPermutation_BruteForce(s1, i);
Assert.AreEqual(ss, s);
}
s1 = "1234";
perms1 = new string[] { "1234", "1243", "1324", "1342", "1423", "1432",
"2134", "2143", "2314", "2341", "2413", "2431",
"3124", "3142", "3214", "3241", "3412", "3421",
"4123", "4132", "4213", "4231", "4312", "4321"};
for (int i = 1; i <= 24; i++)
{
string s = this.GetKthPermutation(s1, i);
Assert.AreEqual(s, perms1[i - 1]);
string ss = this.GetKthPermutation_BruteForce(s1, i);
Assert.AreEqual(ss, s);
}
}

Find a pair of elements from an array whose sum equals a given number

Given array of n integers and given a number X, find all the unique pairs of elements (a,b), whose summation is equal to X.
The following is my solution, it is O(nLog(n)+n), but I am not sure whether or not it is optimal.
int main(void)
{
int arr [10] = {1,2,3,4,5,6,7,8,9,0};
findpair(arr, 10, 7);
}
void findpair(int arr[], int len, int sum)
{
std::sort(arr, arr+len);
int i = 0;
int j = len -1;
while( i < j){
while((arr[i] + arr[j]) <= sum && i < j)
{
if((arr[i] + arr[j]) == sum)
cout << "(" << arr[i] << "," << arr[j] << ")" << endl;
i++;
}
j--;
while((arr[i] + arr[j]) >= sum && i < j)
{
if((arr[i] + arr[j]) == sum)
cout << "(" << arr[i] << "," << arr[j] << ")" << endl;
j--;
}
}
}
There are 3 approaches to this solution:
Let the sum be T and n be the size of array
Approach 1:
The naive way to do this would be to check all combinations (n choose 2). This exhaustive search is O(n2).
Approach 2:
A better way would be to sort the array. This takes O(n log n)
Then for each x in array A,
use binary search to look for T-x. This will take O(nlogn).
So, overall search is O(n log n)
Approach 3 :
The best way
would be to insert every element into a hash table (without sorting). This takes O(n) as constant time insertion.
Then for every x,
we can just look up its complement, T-x, which is O(1).
Overall the run time of this approach is O(n).
You can refer more here.Thanks.
# Let arr be the given array.
# And K be the give sum
for i=0 to arr.length - 1 do
# key is the element and value is its index.
hash(arr[i]) = i
end-for
for i=0 to arr.length - 1 do
# if K-th element exists and it's different then we found a pair
if hash(K - arr[i]) != i
print "pair i , hash(K - arr[i]) has sum K"
end-if
end-for
Implementation in Java : Using codaddict's algorithm (Maybe slightly different)
import java.util.HashMap;
public class ArrayPairSum {
public static void main(String[] args) {
int []a = {2,45,7,3,5,1,8,9};
printSumPairs(a,10);
}
public static void printSumPairs(int []input, int k){
Map<Integer, Integer> pairs = new HashMap<Integer, Integer>();
for(int i=0;i<input.length;i++){
if(pairs.containsKey(input[i]))
System.out.println(input[i] +", "+ pairs.get(input[i]));
else
pairs.put(k-input[i], input[i]);
}
}
}
For input = {2,45,7,3,5,1,8,9} and if Sum is 10
Output pairs:
3,7
8,2
9,1
Some notes about the solution :
We iterate only once through the array --> O(n) time
Insertion and lookup time in Hash is O(1).
Overall time is O(n), although it uses extra space in terms of hash.
Solution in java. You can add all the String elements to an ArrayList of strings and return the list. Here I am just printing it out.
void numberPairsForSum(int[] array, int sum) {
HashSet<Integer> set = new HashSet<Integer>();
for (int num : array) {
if (set.contains(sum - num)) {
String s = num + ", " + (sum - num) + " add up to " + sum;
System.out.println(s);
}
set.add(num);
}
}
Python Implementation:
import itertools
list = [1, 1, 2, 3, 4, 5,]
uniquelist = set(list)
targetsum = 5
for n in itertools.combinations(uniquelist, 2):
if n[0] + n[1] == targetsum:
print str(n[0]) + " + " + str(n[1])
Output:
1 + 4
2 + 3
C++11, run time complexity O(n):
#include <vector>
#include <unordered_map>
#include <utility>
std::vector<std::pair<int, int>> FindPairsForSum(
const std::vector<int>& data, const int& sum)
{
std::unordered_map<int, size_t> umap;
std::vector<std::pair<int, int>> result;
for (size_t i = 0; i < data.size(); ++i)
{
if (0 < umap.count(sum - data[i]))
{
size_t j = umap[sum - data[i]];
result.push_back({data[i], data[j]});
}
else
{
umap[data[i]] = i;
}
}
return result;
}
Here is a solution witch takes into account duplicate entries. It is written in javascript and assumes array is sorted. The solution runs in O(n) time and does not use any extra memory aside from variable.
var count_pairs = function(_arr,x) {
if(!x) x = 0;
var pairs = 0;
var i = 0;
var k = _arr.length-1;
if((k+1)<2) return pairs;
var halfX = x/2;
while(i<k) {
var curK = _arr[k];
var curI = _arr[i];
var pairsThisLoop = 0;
if(curK+curI==x) {
// if midpoint and equal find combinations
if(curK==curI) {
var comb = 1;
while(--k>=i) pairs+=(comb++);
break;
}
// count pair and k duplicates
pairsThisLoop++;
while(_arr[--k]==curK) pairsThisLoop++;
// add k side pairs to running total for every i side pair found
pairs+=pairsThisLoop;
while(_arr[++i]==curI) pairs+=pairsThisLoop;
} else {
// if we are at a mid point
if(curK==curI) break;
var distK = Math.abs(halfX-curK);
var distI = Math.abs(halfX-curI);
if(distI > distK) while(_arr[++i]==curI);
else while(_arr[--k]==curK);
}
}
return pairs;
}
I solved this during an interview for a large corporation. They took it but not me.
So here it is for everyone.
Start at both side of the array and slowly work your way inwards making sure to count duplicates if they exist.
It only counts pairs but can be reworked to
find the pairs
find pairs < x
find pairs > x
Enjoy!
O(n)
def find_pairs(L,sum):
s = set(L)
edgeCase = sum/2
if L.count(edgeCase) ==2:
print edgeCase, edgeCase
s.remove(edgeCase)
for i in s:
diff = sum-i
if diff in s:
print i, diff
L = [2,45,7,3,5,1,8,9]
sum = 10
find_pairs(L,sum)
Methodology: a + b = c, so instead of looking for (a,b) we look for a = c -
b
Implementation in Java : Using codaddict's algorithm:
import java.util.Hashtable;
public class Range {
public static void main(String[] args) {
// TODO Auto-generated method stub
Hashtable mapping = new Hashtable();
int a[]= {80,79,82,81,84,83,85};
int k = 160;
for (int i=0; i < a.length; i++){
mapping.put(a[i], i);
}
for (int i=0; i < a.length; i++){
if (mapping.containsKey(k - a[i]) && (Integer)mapping.get(k-a[i]) != i){
System.out.println(k-a[i]+", "+ a[i]);
}
}
}
}
Output:
81, 79
79, 81
If you want duplicate pairs (eg: 80,80) also then just remove && (Integer)mapping.get(k-a[i]) != i from the if condition and you are good to go.
Just attended this question on HackerRank and here's my 'Objective C' Solution:
-(NSNumber*)sum:(NSArray*) a andK:(NSNumber*)k {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
long long count = 0;
for(long i=0;i<a.count;i++){
if(dict[a[i]]) {
count++;
NSLog(#"a[i]: %#, dict[array[i]]: %#", a[i], dict[a[i]]);
}
else{
NSNumber *calcNum = #(k.longLongValue-((NSNumber*)a[i]).longLongValue);
dict[calcNum] = a[i];
}
}
return #(count);
}
Hope it helps someone.
this is the implementation of O(n*lg n) using binary search implementation inside a loop.
#include <iostream>
using namespace std;
bool *inMemory;
int pairSum(int arr[], int n, int k)
{
int count = 0;
if(n==0)
return count;
for (int i = 0; i < n; ++i)
{
int start = 0;
int end = n-1;
while(start <= end)
{
int mid = start + (end-start)/2;
if(i == mid)
break;
else if((arr[i] + arr[mid]) == k && !inMemory[i] && !inMemory[mid])
{
count++;
inMemory[i] = true;
inMemory[mid] = true;
}
else if(arr[i] + arr[mid] >= k)
{
end = mid-1;
}
else
start = mid+1;
}
}
return count;
}
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
inMemory = new bool[10];
for (int i = 0; i < 10; ++i)
{
inMemory[i] = false;
}
cout << pairSum(arr, 10, 11) << endl;
return 0;
}
In python
arr = [1, 2, 4, 6, 10]
diff_hash = {}
expected_sum = 3
for i in arr:
if diff_hash.has_key(i):
print i, diff_hash[i]
key = expected_sum - i
diff_hash[key] = i
Nice solution from Codeaddict. I took the liberty of implementing a version of it in Ruby:
def find_sum(arr,sum)
result ={}
h = Hash[arr.map {|i| [i,i]}]
arr.each { |l| result[l] = sum-l if h[sum-l] && !result[sum-l] }
result
end
To allow duplicate pairs (1,5), (5,1) we just have to remove the && !result[sum-l] instruction
Here is Java code for three approaches:
1. Using Map O(n), HashSet can also be used here.
2. Sort array and then use BinarySearch to look for complement O(nLog(n))
3. Traditional BruteForce two loops O(n^2)
public class PairsEqualToSum {
public static void main(String[] args) {
int a[] = {1,10,5,8,2,12,6,4};
findPairs1(a,10);
findPairs2(a,10);
findPairs3(a,10);
}
//Method1 - O(N) use a Map to insert values as keys & check for number's complement in map
static void findPairs1(int[]a, int sum){
Map<Integer, Integer> pairs = new HashMap<Integer, Integer>();
for(int i=0; i<a.length; i++){
if(pairs.containsKey(sum-a[i]))
System.out.println("("+a[i]+","+(sum-a[i])+")");
else
pairs.put(a[i], 0);
}
}
//Method2 - O(nlog(n)) using Sort
static void findPairs2(int[]a, int sum){
Arrays.sort(a);
for(int i=0; i<a.length/2; i++){
int complement = sum - a[i];
int foundAtIndex = Arrays.binarySearch(a,complement);
if(foundAtIndex >0 && foundAtIndex != i) //to avoid situation where binarySearch would find the original and not the complement like "5"
System.out.println("("+a[i]+","+(sum-a[i])+")");
}
}
//Method 3 - Brute Force O(n^2)
static void findPairs3(int[]a, int sum){
for(int i=0; i<a.length; i++){
for(int j=i; j<a.length;j++){
if(a[i]+a[j] == sum)
System.out.println("("+a[i]+","+a[j]+")");
}
}
}
}
A Simple program in java for arrays having unique elements:
import java.util.*;
public class ArrayPairSum {
public static void main(String[] args) {
int []a = {2,4,7,3,5,1,8,9,5};
sumPairs(a,10);
}
public static void sumPairs(int []input, int k){
Set<Integer> set = new HashSet<Integer>();
for(int i=0;i<input.length;i++){
if(set.contains(input[i]))
System.out.println(input[i] +", "+(k-input[i]));
else
set.add(k-input[i]);
}
}
}
A simple Java code snippet for printing the pairs below:
public static void count_all_pairs_with_given_sum(int arr[], int S){
if(arr.length < 2){
return;
}
HashSet values = new HashSet(arr.length);
for(int value : arr)values.add(value);
for(int value : arr){
int difference = S - value;
if(values.contains(difference) && value<difference){
System.out.printf("(%d, %d) %n", value, difference);
}
}
}
Another solution in Swift: the idea is to create an hash that store values of (sum - currentValue) and compare this to the current value of the loop. The complexity is O(n).
func findPair(list: [Int], _ sum: Int) -> [(Int, Int)]? {
var hash = Set<Int>() //save list of value of sum - item.
var dictCount = [Int: Int]() //to avoid the case A*2 = sum where we have only one A in the array
var foundKeys = Set<Int>() //to avoid duplicated pair in the result.
var result = [(Int, Int)]() //this is for the result.
for item in list {
//keep track of count of each element to avoid problem: [2, 3, 5], 10 -> result = (5,5)
if (!dictCount.keys.contains(item)) {
dictCount[item] = 1
} else {
dictCount[item] = dictCount[item]! + 1
}
//if my hash does not contain the (sum - item) value -> insert to hash.
if !hash.contains(sum-item) {
hash.insert(sum-item)
}
//check if current item is the same as another hash value or not, if yes, return the tuple.
if hash.contains(item) &&
(dictCount[item] > 1 || sum != item*2) // check if we have item*2 = sum or not.
{
if !foundKeys.contains(item) && !foundKeys.contains(sum-item) {
foundKeys.insert(item) //add to found items in order to not to add duplicated pair.
result.append((item, sum-item))
}
}
}
return result
}
//test:
let a = findPair([2,3,5,4,1,7,6,8,9,5,3,3,3,3,3,3,3,3,3], 14) //will return (8,6) and (9,5)
My Solution - Java - Without duplicates
public static void printAllPairSum(int[] a, int x){
System.out.printf("printAllPairSum(%s,%d)\n", Arrays.toString(a),x);
if(a==null||a.length==0){
return;
}
int length = a.length;
Map<Integer,Integer> reverseMapOfArray = new HashMap<>(length,1.0f);
for (int i = 0; i < length; i++) {
reverseMapOfArray.put(a[i], i);
}
for (int i = 0; i < length; i++) {
Integer j = reverseMapOfArray.get(x - a[i]);
if(j!=null && i<j){
System.out.printf("a[%d] + a[%d] = %d + %d = %d\n",i,j,a[i],a[j],x);
}
}
System.out.println("------------------------------");
}
This prints the pairs and avoids duplicates using bitwise manipulation.
public static void findSumHashMap(int[] arr, int key) {
Map<Integer, Integer> valMap = new HashMap<Integer, Integer>();
for(int i=0;i<arr.length;i++)
valMap.put(arr[i], i);
int indicesVisited = 0;
for(int i=0;i<arr.length;i++) {
if(valMap.containsKey(key - arr[i]) && valMap.get(key - arr[i]) != i) {
if(!((indicesVisited & ((1<<i) | (1<<valMap.get(key - arr[i])))) > 0)) {
int diff = key-arr[i];
System.out.println(arr[i] + " " +diff);
indicesVisited = indicesVisited | (1<<i) | (1<<valMap.get(key - arr[i]));
}
}
}
}
I bypassed the bit manuplation and just compared the index values. This is less than the loop iteration value (i in this case). This will not print the duplicate pairs and duplicate array elements also.
public static void findSumHashMap(int[] arr, int key) {
Map<Integer, Integer> valMap = new HashMap<Integer, Integer>();
for (int i = 0; i < arr.length; i++) {
valMap.put(arr[i], i);
}
for (int i = 0; i < arr.length; i++) {
if (valMap.containsKey(key - arr[i])
&& valMap.get(key - arr[i]) != i) {
if (valMap.get(key - arr[i]) < i) {
int diff = key - arr[i];
System.out.println(arr[i] + " " + diff);
}
}
}
}
in C#:
int[] array = new int[] { 1, 5, 7, 2, 9, 8, 4, 3, 6 }; // given array
int sum = 10; // given sum
for (int i = 0; i <= array.Count() - 1; i++)
if (array.Contains(sum - array[i]))
Console.WriteLine("{0}, {1}", array[i], sum - array[i]);
One Solution can be this, but not optimul (The complexity of this code is O(n^2)):
public class FindPairsEqualToSum {
private static int inputSum = 0;
public static List<String> findPairsForSum(int[] inputArray, int sum) {
List<String> list = new ArrayList<String>();
List<Integer> inputList = new ArrayList<Integer>();
for (int i : inputArray) {
inputList.add(i);
}
for (int i : inputArray) {
int tempInt = sum - i;
if (inputList.contains(tempInt)) {
String pair = String.valueOf(i + ", " + tempInt);
list.add(pair);
}
}
return list;
}
}
A simple python version of the code that find a pair sum of zero and can be modify to find k:
def sumToK(lst):
k = 0 # <- define the k here
d = {} # build a dictionary
# build the hashmap key = val of lst, value = i
for index, val in enumerate(lst):
d[val] = index
# find the key; if a key is in the dict, and not the same index as the current key
for i, val in enumerate(lst):
if (k-val) in d and d[k-val] != i:
return True
return False
The run time complexity of the function is O(n) and Space: O(n) as well.
public static int[] f (final int[] nums, int target) {
int[] r = new int[2];
r[0] = -1;
r[1] = -1;
int[] vIndex = new int[0Xfff];
for (int i = 0; i < nums.length; i++) {
int delta = 0Xff;
int gapIndex = target - nums[i] + delta;
if (vIndex[gapIndex] != 0) {
r[0] = vIndex[gapIndex];
r[1] = i + 1;
return r;
} else {
vIndex[nums[i] + delta] = i + 1;
}
}
return r;
}
less than o(n) solution will be=>
function(array,k)
var map = {};
for element in array
map(element) = true;
if(map(k-element))
return {k,element}
Solution in Python using list comprehension
f= [[i,j] for i in list for j in list if j+i==X];
O(N2)
also gives two ordered pairs- (a,b) and (b,a) as well
I can do it in O(n). Let me know when you want the answer. Note it involves simply traversing the array once with no sorting, etc... I should mention too that it exploits commutativity of addition and doesn't use hashes but wastes memory.
using System;
using System.Collections.Generic;
/*
An O(n) approach exists by using a lookup table. The approach is to store the value in a "bin" that can easily be looked up(e.g., O(1)) if it is a candidate for an appropriate sum.
e.g.,
for each a[k] in the array we simply put the it in another array at the location x - a[k].
Suppose we have [0, 1, 5, 3, 6, 9, 8, 7] and x = 9
We create a new array,
indexes value
9 - 0 = 9 0
9 - 1 = 8 1
9 - 5 = 4 5
9 - 3 = 6 3
9 - 6 = 3 6
9 - 9 = 0 9
9 - 8 = 1 8
9 - 7 = 2 7
THEN the only values that matter are the ones who have an index into the new table.
So, say when we reach 9 or equal we see if our new array has the index 9 - 9 = 0. Since it does we know that all the values it contains will add to 9. (note in this cause it's obvious there is only 1 possible one but it might have multiple index values in it which we need to store).
So effectively what we end up doing is only having to move through the array once. Because addition is commutative we will end up with all the possible results.
For example, when we get to 6 we get the index into our new table as 9 - 6 = 3. Since the table contains that index value we know the values.
This is essentially trading off speed for memory.
*/
namespace sum
{
class Program
{
static void Main(string[] args)
{
int num = 25;
int X = 10;
var arr = new List<int>();
for(int i = 0; i <= num; i++) arr.Add((new Random((int)(DateTime.Now.Ticks + i*num))).Next(0, num*2));
Console.Write("["); for (int i = 0; i < num - 1; i++) Console.Write(arr[i] + ", "); Console.WriteLine(arr[arr.Count-1] + "] - " + X);
var arrbrute = new List<Tuple<int,int>>();
var arrfast = new List<Tuple<int,int>>();
for(int i = 0; i < num; i++)
for(int j = i+1; j < num; j++)
if (arr[i] + arr[j] == X)
arrbrute.Add(new Tuple<int, int>(arr[i], arr[j]));
int M = 500;
var lookup = new List<List<int>>();
for(int i = 0; i < 1000; i++) lookup.Add(new List<int>());
for(int i = 0; i < num; i++)
{
// Check and see if we have any "matches"
if (lookup[M + X - arr[i]].Count != 0)
{
foreach(var j in lookup[M + X - arr[i]])
arrfast.Add(new Tuple<int, int>(arr[i], arr[j]));
}
lookup[M + arr[i]].Add(i);
}
for(int i = 0; i < arrbrute.Count; i++)
Console.WriteLine(arrbrute[i].Item1 + " + " + arrbrute[i].Item2 + " = " + X);
Console.WriteLine("---------");
for(int i = 0; i < arrfast.Count; i++)
Console.WriteLine(arrfast[i].Item1 + " + " + arrfast[i].Item2 + " = " + X);
Console.ReadKey();
}
}
}
I implemented logic in Scala with out a Map. It gives duplicate pairs since the counter loops thru entire elements of the array. If duplicate pairs are needed, you can simply return the value pc
val arr = Array[Int](8, 7, 2, 5, 3, 1, 5)
val num = 10
var pc = 0
for(i <- arr.indices) {
if(arr.contains(Math.abs(arr(i) - num))) pc += 1
}
println(s"Pairs: ${pc/2}")
It is working with duplicates values in the array as well.
GOLANG Implementation
func findPairs(slice1 []int, sum int) [][]int {
pairMap := make(map[int]int)
var SliceOfPairs [][]int
for i, v := range slice1 {
if valuei, ok := pairMap[v]; ok {
//fmt.Println("Pair Found", i, valuei)
SliceOfPairs = append(SliceOfPairs, []int{i, valuei})
} else {
pairMap[sum-v] = i
}
}
return SliceOfPairs
}
function findPairOfNumbers(arr, targetSum) {
arr = arr.sort();
var low = 0, high = arr.length - 1, sum, result = [];
while(low < high) {
sum = arr[low] + arr[high];
if(sum < targetSum)
low++;
else if(sum > targetSum)
high--;
else if(sum === targetSum) {
result.push({val1: arr[low], val2: arr[high]});
high--;
}
}
return (result || false);
}
var pairs = findPairOfNumbers([1,2,3,4,5,6,7,8,9,0], 7);
if(pairs.length) {
console.log(pairs);
} else {
console.log("No pair of numbers found that sums to " + 7);
}

Resources