Related
Given an integer array, find the maximum sum of subsequence where the subsequence contains no element at adjacent positions.
Input: { 1, 2, 9, 4, 5, 0, 4, 11, 6 }
Output: The maximum sum is 26
The maximum sum is formed by subsequence { 1, 9, 5, 11 }
My below code is working fine .helper2 method is same as findMaxSumSubsequence but with memoisation.Both these methods call themselves recursively exploring all subsets i.e take the element at ith pos or not take the element at ith position.
private int findMaxSumSubsequence(int[] arr ,int i ,boolean flag) {
if( i>=arr.length)
return 0;
int incAns=0;
if(!flag)
{
incAns=findMaxSumSubsequence(arr,i+1,true) + arr[i];
}
int exAns=findMaxSumSubsequence(arr,i+1,false) ;
return Math.max(incAns, exAns);
But when i try to memoise the code I get the wrong answer for
helper2(nums,0,false) //method call
nums={1,2} after memoisation i get answer as 1 .Correct answer is 2.
int[] memo is initialised with -1 .
int[] memo = new int[101];
private int helper2(int[] arr ,int i ,boolean flag) {
if( i>=arr.length)
return memo[i]=0;
if(memo[i]!=-1)
return memo[i];
int incAns=0;
if(!flag)
{
incAns=helper2(arr,i+1,true) + arr[i];
}
int exAns=helper2(arr,i+1,false) ;
memo[i]= Math.max(incAns, exAns);
return Math.max(incAns, exAns);
You are missing the second memoization parameter 'flag', that's why you have a wrong answer, it should be:
int[][] memo = new int[101][2];
instead of
int[] memo = new int[101];
code:
int[][] memo = new int[101][2];
int [] arr;
private int helper2(int i ,boolean flag) {
if (i >= arr.length)
return 0;
if (memo[i][flag? 1 : 0] != -1) return memo[i][flag ? 1 : 0];
int incAns = 0;
if (!flag) {
incAns = helper2( i + 1, true) + arr[i];
}
int exAns = helper2( i + 1, false);
return memo[i][flag? 1 : 0] = Math.max(incAns, exAns);
}
public static void main(String[] args) {
arr = new int[]{1, 2};
for(int i = 0; i < 100; i++) Arrays.fill(memo[i], -1);
out.println(helper2(0, false));
}
Also no need to add the array as a parameter in the recursive function because it's static and don't change, otherwise you will get Memory Limit Exceeded.
So the problem is:
Write a program to find the nth super ugly number.
Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes of size k. For example, [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] is the sequence of the first 12 super ugly numbers given primes = [2, 7, 13, 19] of size 4.
So my algorithm basically finds all possible factors using the pattern they follow, pushes them to an array, sorts that array and then returns the nth value in the array. It accurately calculates all of them, however, is too slow with high nth values.
My question is what the proper way to do this is as I'm sure there has to be a more straightforward solution. I'm mostly curious about the theory behind finding it and if there's some kind of closed formula for this.
var nthSuperUglyNumber = function(n, primes) {
xprimes = primes;
var uglies = [1];
uglies = getUglyNumbers(n, primes, uglies);
// return uglies[n-1];
return uglies[n - 1];
};
// 3 4
//1, 2,3,5, || 4,6,10, 9,15, 25, || 8,12,20,18,30,50, 27,45,75, 125 ||
// 3,2,1 6,3,1, 10,4,1
// 1 1 1
//1, 2,3 || 4,6, 9, || 8,12,18, 27 || 16,24,36,54, 81
// 2,1 3,1 4,1 5,1
//
//1, 2,3,5,7 || 4,6,10,14 9,15,21 25,35, 49 ||
// 4,3,2,1 || 10,6,3,1
var getUglyNumbers = function(n, primes, uglies) {
if (n == 1) {
return uglies;
}
var incrFactor = [];
var j = 0;
// Initial factor and uglies setup
for (; j < primes.length; j += 1) {
incrFactor[j] = primes.length - j;
uglies.push(primes[j]);
}
//recrusive algo
uglies = calcUglies(n, uglies, incrFactor);
uglies.sort(function(a, b) {
return a - b;
});
return uglies;
};
var calcUglies = function(n, uglies, incrFactor) {
if (uglies.length >= 5 * n) return uglies;
var currlength = uglies.length;
var j = 0;
for (j = 0; j < xprimes.length; j += 1) {
var i = 0;
var start = currlength - incrFactor[j];
for (i = start; i < currlength; i += 1) {
uglies.push(xprimes[j] * uglies[i]);
}
}
// Upgrades the factors to level 2
for (j = 1; j < xprimes.length; j += 1) {
incrFactor[xprimes.length - 1 - j] = incrFactor[xprimes.length - j] + incrFactor[xprimes.length - 1 - j];
}
return calcUglies(n, uglies, incrFactor);
};
public static ArrayList<Integer> superUgly(int[] primes,int size)
{
Arrays.sort(primes);
int pLen = primes.length;
ArrayList<Integer> ans = new ArrayList<>();
ans.add(1);
PriorityQueue<pair> priorityQueue = new PriorityQueue<>(Comparator.comparingInt(p -> p.value));
HashSet<Integer> hashSet = new HashSet<>();
int next_ugly_number;
int[] indices = new int[pLen];
for(int i=0;i<pLen;i++) {
hashSet.add(primes[i]);
priorityQueue.add(new pair(i,primes[i]));
}
while(ans.size()!=size+1)
{
pair pair = priorityQueue.poll();
next_ugly_number = pair.value;
ans.add(next_ugly_number);
indices[pair.index]+=1;
int temp = ans.get(indices[pair.index])*primes[pair.index];
if (!hashSet.contains(temp))
{
priorityQueue.add(new pair(pair.index,temp));
hashSet.add(temp);
}
else {
while(hashSet.contains(temp))
{
indices[pair.index]+=1;
temp = ans.get(indices[pair.index])*primes[pair.index];
}
priorityQueue.add(new pair(pair.index,temp));
hashSet.add(temp);
}
}
ans.remove(0);
return ans;
}
Pair class is
class pair
{
int index,value;
public pair(int i,int v)
{
index = i;
value = v;
}
}
It returns a list of ugly numbers of size 'size'.
I am using priority queue to find minimum for every loop and also a hashset to avoid duplicate entries in priorityQueue.
So its time complexity is O(n log(k)) where n is size and k is primes array size.
This is the most optimal solution I could write using Dynamic Programming in Python.
Time complexity: O(n * k)
Space Complexity: O(n)
from typing import List
def super_ugly_numbers(n: int, primes: List[int]) -> int:
# get nth super ugly number
ugly_nums = [0] * n
ugly_nums[0] = 1
length = len(primes)
mul_indices = [0] * length
multipliers = primes[:]
for index in range(1, n):
ugly_nums[index] = min(multipliers)
for in_index in range(length):
if ugly_nums[index] == multipliers[in_index]:
mul_indices[in_index] += 1
multipliers[in_index] = ugly_nums[mul_indices[in_index]] * primes[in_index]
return ugly_nums[n-1]
This algorithm performs better for large n.
primes := {2, 7, 13, 19}
set list := {1}
for i in 1..n-1:
set k = list[0]
for p in primes:
insert p*k into list unless p*k is in list
remove list[0] from list
return list[0]
If inserting in order is hard, you can just insert the elements into the list at the end and sort the list just after removing list[0].
import java.util.*;
import java.lang.*;
import java.io.*;
public class Solution{
public static void main(String[] args) {
Scanner fi = new Scanner(System.in);
int n=fi.nextInt();
int i;
int primes[] ={2,3,5};
HashSet<Integer> hm=new HashSet<>();
PriorityQueue<Integer> pq=new PriorityQueue<>();
TreeSet<Integer> tr=new TreeSet<>();
tr.add(1);
pq.add(1);
hm.add(1);
for (i=0;i<primes.length;i++){
tr.add(primes[i]);
pq.add(primes[i]);
hm.add(primes[i]);
}
int size=tr.size();
while (size < n){
int curr=pq.poll();
for (i=0;i<primes.length;i++){
if (!hm.contains(curr*primes[i])) {
tr.add(curr * primes[i]);
hm.add(curr*primes[i]);
pq.add(curr*primes[i]);
size++;
}
}
}
System.out.println(tr);
}
}
This might as Help as TreeSet maintains element in sorted order so need to worry about index.
Given an input array we can find a single sub-array which sums to K (given) in linear time, by keeping track of sum found so far and the start position. If the current sum becomes greater than the K we keep removing elements from start position until we get current sum <= K.
I found sample code from geeksforgeeks and updated it to return all such possible sets. But the assumption is that the input array consists of only +ve numbers.
bool subArraySum(int arr[], int n, int sum)
{
int curr_sum = 0, start = 0, i;
bool found = false;
for (i = 0; i <= n; i++)
{
while (curr_sum > sum && start < i)
{
curr_sum = curr_sum - arr[start];
start++;
}
if (curr_sum == sum)
{
cout<<"Sum found in b/w indices: "<<start<<" & "<<(i-1)<<"\n";
curr_sum -= arr[start];
start++;
found = true;
}
// Add this element to curr_sum
if (i < n) {
curr_sum = curr_sum + arr[i];
}
}
return found;
}
My question is do we have such a solution for mixed set of numbers too (both positive and negative numbers)?
There is no linear-time algorithm for the case of both positive and negative numbers.
Since you need all sub-arrays which sum to K, time complexity of any algorithm cannot be better than size of the resulting set of sub-arrays. And this size may be quadratic. For example, any sub-array of [K, -K, K, -K, K, -K, ...], starting and ending at positive 'K' has the required sum, and there are N2/8 such sub-arrays.
Still it is possible to get the result in O(N) expected time if O(N) additional space is available.
Compute prefix sum for each element of the array and insert the pair (prefix_sum, index) to a hash map, where prefix_sum is the key and index is the value associated with this key. Search prefix_sum - K in this hash map to get one or several array indexes where the resulting sub-arrays start:
hash_map[0] = [-1]
prefix_sum = 0
for index in range(0 .. N-1):
prefix_sum += array[index]
start_list = hash_map[prefix_sum - K]
for each start_index in start_list:
print start_index+1, index
start_list2 = hash_map[prefix_sum]
start_list2.append(index)
Solution as given by #Evgeny Kluev coded in Java with a little explanation.
public static void main(String[] args) {
int[] INPUT = {5, 6, 1, -2, -4, 3, 1, 5};
printSubarrays(INPUT, 5);
}
private static void printSubarrays(int[] input, int k) {
Map<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
List<Integer> initial = new ArrayList<Integer>();
initial.add(-1);
map.put(0, initial);
int preSum = 0;
// Loop across all elements of the array
for(int i=0; i< input.length; i++) {
preSum += input[i];
// If point where sum = (preSum - k) is present, it means that between that
// point and this, the sum has to equal k
if(map.containsKey(preSum - k)) { // Subarray found
List<Integer> startIndices = map.get(preSum - k);
for(int start : startIndices) {
System.out.println("Start: "+ (start+1)+ "\tEnd: "+ i);
}
}
List<Integer> newStart = new ArrayList<Integer>();
if(map.containsKey(preSum)) {
newStart = map.get(preSum);
}
newStart.add(i);
map.put(preSum, newStart);
}
}
Quadratic Time: O(n2) in worst case.
private static void findSubArray(int[] is, int N) {
System.out.println("Continuous sub array of " + Arrays.toString(is) + " whose sum is " + N + " is ");
List<Integer> arry = new ArrayList<>(is.length);
for (int i = 0; i < is.length; i++) {
int tempI = is[i];
arry.add(tempI);
for (int j = i + 1; j < is.length; j++) {
if (tempI + is[j] == N) {
arry.add(is[j]);
System.out.println(arry);
} else if (tempI + is[j] < N) {
arry.add(is[j]);
tempI = tempI + is[j];
} else {
arry.clear();
break;
}
}
}
}
public static void main(String[] args) {
findSubArray(new int[] { 42, 15, 12, 8, 6, 32 }, 26);
findSubArray(new int[] { 12, 5, 31, 13, 21, 8 }, 49);
findSubArray(new int[] { 15, 51, 7, 81, 5, 11, 25 }, 41);
}
This problem is very similar to the combination problem solved here: http://introcs.cs.princeton.edu/java/23recursion/Combinations.java.html
Here is my solution:
public static void main(String[] args) {
int [] input = {-10, 0, 5, 10, 15, 20, 30};
int expectedSum = 20;
combination(new SumObj(new int[0]), new SumObj(input), expectedSum);
}
private static void combination(SumObj prefixSumObj, SumObj remainingSumObj, int expectedSum){
if(prefixSumObj.getSum() == expectedSum){
System.out.println(Arrays.toString(prefixSumObj.getElements()));
}
for(int i=0; i< remainingSumObj.getElements().length ; i++){
// prepare new prefix
int [] newPrefixSumInput = new int[prefixSumObj.getElements().length + 1];
System.arraycopy(prefixSumObj.getElements(), 0, newPrefixSumInput, 0, prefixSumObj.getElements().length);
newPrefixSumInput[prefixSumObj.getElements().length] = remainingSumObj.getElements()[i];
SumObj newPrefixSumObj = new SumObj(newPrefixSumInput);
// prepare new remaining
int [] newRemainingSumInput = new int[remainingSumObj.getElements().length - i - 1];
System.arraycopy(remainingSumObj.getElements(), i+1, newRemainingSumInput, 0, remainingSumObj.getElements().length - i - 1);
SumObj newRemainingSumObj = new SumObj(newRemainingSumInput);
combination(newPrefixSumObj, newRemainingSumObj, expectedSum);
}
}
private static class SumObj {
private int[] elements;
private int sum;
public SumObj(int[] elements) {
this.elements = elements;
this.sum = computeSum();
}
public int[] getElements() {
return elements;
}
public int getSum() {
return sum;
}
private int computeSum(){
int tempSum = 0;
for(int i=0; i< elements.length; i++){
tempSum += elements[i];
}
return tempSum;
}
}
Try this code this can work for you:
private static void printSubArrayOfRequiredSum(int[] array, int requiredSum) {
for (int i = 0; i < array.length; i++) {
String str = "[ ";
int sum = 0;
for (int j = i; j < array.length; j++) {
sum = sum + array[j];
str = str + array[j] + ", ";
if (sum == requiredSum) {
System.out.println(" sum : " + sum + " array : " + str
+ "]");
str = "[ ";
sum = 0;
}
}
}
}
Use this method like :
int array[] = { 3, 5, 6, 9, 14, 8, 2, 12, 7, 7 };
printSubArrayOfRequiredSum(array, 14);
Output :
sum : 14 array : [ 3, 5, 6, ]
sum : 14 array : [ 14, ]
sum : 14 array : [ 2, 12, ]
sum : 14 array : [ 7, 7, ]
Solution as given by #Evgeny Kluev coded in c++
#include<bits/stdc++.h>
using namespace std;
int c=0;
// Function to print subarray with sum as given sum
void subArraySum(int arr[], int n, int k)
{
map<int,vector<int>>m1;
m1[0].push_back(-1);
int curr_sum=0;
for(int i=0;i<n;i++){
curr_sum=curr_sum+arr[i];
if(m1.find(curr_sum-k)!=m1.end()){
vector<int>a=m1[curr_sum-k];
c+=m1[curr_sum-k].size();
for(int j=0;j<a.size();j++){ // printing all indexes with sum=k
cout<<a[j]+1<<" "<<i<<endl;
}
}
m1[curr_sum].push_back(i);
}
}
int main()
{
int arr[] = {10,2,0,10,0,10};
int n = sizeof(arr)/sizeof(arr[0]);
int sum = 10;
subArraySum(arr, n, sum);
cout<<c<<endl; //count of subarrays with given sum
return 0;
}
class Solution
{
//Function to find a continuous sub-array which adds up to a given number.
static ArrayList<Integer> subarraySum(int[] arr, int n, int s)
{
ArrayList<Integer> res=new ArrayList<>();
int i=0,j=0,sum=0;
sum=sum+arr[i];
if(s==0){
res.add(-1);
return res;
}
while(true)
{
if(sum<s)
{
j=j+1;
if(j>=n || i>=n){
res.add(-1);
return res;
}
sum=sum+arr[j];
}else if(sum>s){
sum=sum-arr[i];
i=i+1;
if(sum==s){
res.add(i+1);
res.add(j+1);
return res;
}
}else{
res.add(i+1);
res.add(j+1);
return res;
}
if(j>=n || i>=n){
res.add(-1);
return res;
}
}
}
}
Passing all 165 test cases from geeksforgeeks
I also faced this problem in couple of interviews and came up with following best approach:
class MazSubArraySum {
public static void main(String[] args) {
int[] a = { -2, -3, 4, -1, -2, 1, 5, -3 };
System.out.println("Maximum contiguous sum is " + maxSubArraySum(a));
}
static int maxSubArraySum(int a[]) {
int size = a.length;
int currentindex = 0, end = 0, begin = 0;
int max_so_far = Integer.MIN_VALUE, max_ending_here = 0;
for (int i = 0; i < size; i++) {
max_ending_here = max_ending_here + a[i];
if (max_so_far < max_ending_here) {
max_so_far = max_ending_here;
begin = currentindex;
end = i;
}
if (max_ending_here < 0) {
max_ending_here = 0;
currentindex++;
}
}
System.out.println("begin and end: " + begin + "&" + end);
return max_so_far;
}
}
Below is the output:
begin and end: 2&6
Maximum contiguous sum is 7
Above solution is the best solution in terms of time and space complexity that is O(n).
I came across this question in one Interview. Please help me in getting the solution.
Question is:
You have sorted rotatable array, i. e. the array contains elements which are sorted and it can be rotated circularly, like if the elements in array are [5,6,10,19,20,29] then rotating first time array becomes [29,5,6,10,19,20] and on second time it becomes [20,29,5,6,10,19] and so on.
So you need to find the smallest element in the array at any point. You won’t be provided with number times array is rotated. Just given the rotated array elements and find out the smallest among them. In this case output should be 5.
Method 1:
You can do this in O(logN) time.
Use a modified binary search to find the point of rotation which is an index i such that arr[i] > arr[i+1].
Example:
[6,7,8,9,1,2,3,4,5]
^
i
The two sub-arrays (arr[1], arr[2], .., arr[i]) and (arr[i+1], arr[i+2], ..., arr[n]) are sorted.
The answer is min(arr[1], arr[i+1])
Method 2:
When you split the sorted, rotated array into two halves (arr[1],..,arr[mid]) and (arr[mid+1],..,arr[n]), one of them is always sorted and the other always has the min. We can directly use a modified binary search to keep searching in the unsorted half
// index of first element
l = 0
// index of last element.
h = arr.length - 1
// always restrict the search to the unsorted
// sub-array. The min is always there.
while (arr[l] > arr[h]) {
// find mid.
mid = (l + h)/2
// decide which sub-array to continue with.
if (arr[mid] > arr[h]) {
l = mid + 1
} else {
h = mid
}
}
// answer
return arr[l]
The above algorihtm fails if data element is repeated like {8,8,8,8,8} or {1,8,8,8,8} or {8,1,8,8,8} or {8,8,1,8,8} or {8,8,8,8,1}
// solution pasted below will work all test cases :)
//break the array in two subarray and search for pattern like a[mid]>a[mid+1]
// and return the min position
public static int smallestSearch(int[] array,int start,int end)
{
if(start==end)
return array.length;
int mid=(start+end)/2;
if(array[mid]>array[mid+1])
return min(mid+1,smallestSearch(array,start,mid),smallestSearch(array,mid+1,end));
else
return min(smallestSearch(array,start,mid),smallestSearch(array,mid+1,end));
}
public static int min(int a,int b)
{
if(a==b)
return a;
else if(a<b)
return a;
else
return b;
}
public static int min(int a,int b,int c)
{
if(a<c)
{
if(a<b)
{
return a;
}
else
{
return b;
}
}
else
{
if(b<c)
return b;
else
return c;
}
}
To Find the smallest number in the sorted rotated array:
using Binary search concept
public class RotatedSortedArrayWithoutDuplicates1 {
public static void main(String[] args) {
int[] a = { 4, 6, 8, 10, 34, 56, 78, 1, 3 };
System.out.println(findMin(a));
}
private static int findMin(int[] a) {
if (a.length == 0 || a == null) {
return -1;
}
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = start + (last - start) / 2;
int m = a[mid];
int s = a[start];
int l = a[last];
if (m > l) {
start = mid + 1;
}
if (m < l) {
last = mid;
} else {
last--;
}
} // while
if (a[start] > a[last]) {
return a[last];
} else {
return a[start];
}
}
}
But if you don't want to use Binary Search, then :
public class Abc {
public static void main(String[] args) {
int[] a = { 4, 5, 6, 7, 7, 8, 9, 1, 1, 2, 3, 3 };
System.out.println(findMin(a));
}
public static int findMin(int[] a) {
int min = a[a.length - 1];
for (int i = 0; i < a.length; i++) {
if (min > a[i]) {
min = a[i];
break;
}
}
return min;
}// findmin
}// end
Here is the code in Python:
def fix(a):
min = a[0]
for i in range(len(a)):
if(min > a[i]):
min = a[i]
break
return min
a = [2, 2,3,4,1,2]
print(fix(a))
My code is below with the algorithm as comments. Works even for the repeated elements.
//Find Min in Rotated Sorted Array
//Example: int array[10] = {7, 8, 9, 10, 11, 12, 3, 4, 5, 6};
// Min in the above array is 3
// Solution: Recursively search (Modified binary search) for the Pivot where is the smallest Element is present
// Algorithm:
// 1) Find the Mid of the Array
// 2) call the recursive function on segment of array in which there is a deviation in the order
// If (A[low] > A[mid]) array segment in which deviation in the order present is (low, mid)
// If (A[low] < A[mid]) array segment in which deviation in the order present is (mid + 1, high)
// Time Complexity: O(logn)
// Space Complexity: is of the recursive function stack that is being used
#define MIN(x,y) (x) <= (y) ? (x): (y)
int MininRotatedSortedArray(int A[], int low, int high)
{
if(low > high)
return -1;
if(low == high - 1)
return MIN(A[low], A[high]);
int mid = low + (high - low)/2;
if(A[low] > A[mid])
return MininRotatedSortedArray(A, low, mid);
else if(A[low] < A[mid])
return MininRotatedSortedArray(A, mid + 1, high);
else
return A[mid];
}
This can be done in O(1) time best case, O(n) time worst case, and O(lg n) time on average.
For a rotated sorted array, if the first element in the array is less than the last element in the array, then the sorted array is not rotated (or rotated 0 position). The minimum element is simply the first element.
If the middle element is less than the last element, then the minimum element is in [first, middle].
If the middle element is greater than the last element, then the minimum element is in [middle + 1, last].
If the middle element is equal to the last element, then there are two sub-cases:
the first element is larger than the last element, in which case the minimum element is in [first, middle + 1];
the first element is equal to the last element, in which case it is inconclusive to reject either half of the array. Reduce to linear search. For example, for arrays such as [5,5,5,1,5] and [5,1,5,5,5], it is impossible by just examining the first, last and middle element (since they are all equal) which half of the array the minimum element lies.
I wrote the following code in C++ to solve this problem, which should handle all cases (empty array, repeated elements).
template <typename Iterator>
Iterator rotated_min(Iterator begin, Iterator end)
{
while (begin != end)
{
if (*begin < *(end - 1))
{
return begin;
}
Iterator mid = begin + (end - 1 - begin) / 2;
if (*mid < *(end - 1))
{
end = mid + 1;
}
else if (*mid > *(end - 1))
{
begin = mid + 1;
}
else
{
if (*begin > *(end - 1))
{
end = mid + 1;
++begin;
}
else
{
//reduce to linear search
typename ::std::iterator_traits<Iterator>::value_type min_value = *begin;
Iterator min_element = begin;
for (Iterator i = begin + 1; i != end; ++i)
{
if (*i < min_value)
{
min_value = *i;
min_element = i;
}
}
return min_element;
}
}
}
return begin;
}
Find Min index in circular sorted array
Example : [7,8,9,1,2,3,4,5,6]
int findMinIndex(int []a, int start, int end)
{
int mid = (start + end)/2;
if (start - end == 1)
if(a[start] < a[end])
return start;
else
return end;
if (a[mid] > a[end]){
return findMinIndex(a,mid,end);
}
else{
return findMinIndex(a,start,mid);
}
return -1; //Not found
}
In case any one needs it.. My implementation in java..
takes care of sorted/unsorted ascending//descending order usecases..
drawback is it will still perform log n steps to find min value in a perfectly sorted set with no rotation.
http://ideone.com/fork/G3zMIb
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
int [] a = {3,3,0,2,2,2,2,1,2,2,2,2,2,2,2,2,2};
System.out.println(recursiveSplit(a,0,a.length-1));
}
public static int findMin(int x, int y){
if(x<=y){
return x;
}else{
return y;
}
}
public static int recursiveSplit(int[] arr , int a , int b){
int mid = (int) Math.floor(a + (b-a)/2);
int h1_l = a;
int h1_u = mid;
int h2_l = mid+1;
int h2_u = b;
int x=0;
int y=0;
//single element
if(a==b){
return arr[a];
}
//adjacent positions
if(h1_u-h1_l==1){
x=findMin(arr[h1_u],arr[h1_l]);
}else{
//else split
x=recursiveSplit(arr,h1_l,h1_u);
}
if(h2_u-h2_l==1){
y=findMin(arr[h2_u],arr[h2_l]);
}else{
y=recursiveSplit(arr, h2_l,h2_u);
}
return findMin(x, y);
}
}
Errors/suggestions/failed usecases are welcomed
public int findMin(int[] num) {
return findMin(num, 0, num.length-1);
}
public int findMin(int[] num, int left, int right){
if(left==right) return num[left];
if(left+1==right) return Math.min(num[left], num[right]);
int mid = (left+right)/2;
if(num[mid]>num[right]){
return findMin(num,mid+1,right);
}else if(num[mid]<num[right]){
return findMin(num,left,mid);
}else{
if(num[mid]==num[left]){
return Math.min(findMin(num,left,mid), findMin(num,mid,right));
}else{
return findMin(num,left,mid);
}
}
}
The following algorithm takes log(n) time. Assuming the array has no duplicate.
public int findMin(int[] num) {
if(num.length == 0) return -1
int r = num.length-1, l = 0;
while(l<r){
if(num[l]<=num[r]) return num[l]; //when not rotated, return the left most value
int mid = (r+l)/2;
if(num[mid]<num[r]){
r = mid;
}else{
l = mid+1;
}
}
return num[l];
}
I did it using a slightly modified version of binary search. What I am doing here is I keep going left or right based on where the minimum could be. For example in an ascending array if the mid element is less than the left most element, its possible that the minimum is to the left. While recursing thru the array, I also keep track of the minimum. The recursion continues until the end and then the latest min is returned. This also works with repeated elements.
public static void main(String[] args) throws IOException {
int[] rotated = {6, 7, 8, 1, 2, 3, 4, 5};
int min = findMin(rotated);
System.out.println(min);//1
}
public static int findMin(int[] sorted) {
return findMinRecursively(sorted, sorted[0], 0, (sorted.length - 1));
}
private static int findMinRecursively(int[] sorted, int min, int leftIndex, int rightIndex) {
if (leftIndex > rightIndex) {
return min;
}
int midIndex = (leftIndex + rightIndex) / 2;
if (sorted[midIndex] < min) {
min = sorted[midIndex];
}
if (sorted[midIndex] < sorted[leftIndex]) {
return findMinRecursively(sorted, min, leftIndex, (midIndex - 1));
} else {
return findMinRecursively(sorted, min, (midIndex + 1), rightIndex);
}
}
Question : Find minimum in a sorted rotated array .
Solution 1 : Using Binary Search
class Test18 {
public static void main(String[] args) {
int[] a = { 5, 6, 7, 8, 9, 10, 1, 2, 3 };
System.out.println(findmin(a));
}
// find min in a sorted rotated array
private static int findmin(int[] a) {
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = start + (last - start) / 2;
if (a[mid] > a[last]) {
start = mid + 1;
}
if (a[mid] < a[last]) {
last = mid;
} else {
mid--;
}
} // while
if (a[start] > a[last]) {
return a[last];
} else {
return a[start];
}
}
}
def searchinrotatedarray(arr1,l,h):
if l>h:
return arr1[0]
if h==l:
return arr1[l]
mid=(l+h)//2
if mid<h and arr1[mid+1]<arr1[mid]:
return arr1[mid+1]
elif mid>l and arr1[mid-1]<arr1[mid]:
return arr1[mid]
elif arr1[mid]<arr1[h]:
return searchinrotatedarray(arr1,l,mid-1)
else:
return searchinrotatedarray(arr1,mid+1,h)
first if statement checks if even array is rotated at all. in that case first element is the min . if length of list is 1 then that element is min.
else if mid element is less than last element then continue to look in second half else look for the element in first half
//java program to find minimum element in a sorted array rotated
//about any pivot in O(log n) in worst case and O(1) in best case
class ArrayRotateMinimum {
public static void main(String str[]) {
// initialize with your sorted rotated array here
int array[] = { 9, 1, 2, 3, 4, 5, 6, 7, 8, };
System.out.println("Minimum element is: " + minimumElement(array));
}
static int minimumElement(int array[]) {
// variables to keep track of low and high indices
int low, mid, high;
// initializing variables with appropriate values
low = 0;
high = array.length - 1;
while (low < high) {
// mid is always defined to be the average of low and high
mid = (low + high) / 2;
if (array[low] > array[mid]) {
// for eg if array is of the form [9,1,2,4,5],
// then shift high to mid to reduce array size by half
// while keeping minimum element between low and high
high = mid;
} else if (array[mid] > array[high]) {
// this condition deals with the end case when the final two
// elements in the array are of the form [9,1] during the
// last iteration of the while loop
if (low == mid) {
return array[high];
}
// for eg if array is of the form [4,5,9,1,2],
// then shift low to mid to reduce array size by half
// while keeping minimum element between low and high
low = mid;
} else {
// the array has not been rotated at all
// hence the first element happens to be the smallest element
return array[low];
}
}
//return first element in case array size is just 1
return array[0];
}
}
This is my pythonic solution using recursion:
Time complexity is O(log(n)) & Space complexity: O(1)
class Solution(object):
def findMin(self, nums):
left = 0
right = len(nums) -1
mid = len(nums) // 2
if len(nums) == 0:
return -1
if len(nums) == 1:
return nums[left]
if len(nums) == 2:
return min(nums[left], nums[right])
if nums[left] < nums[right]:
return nums[left]
elif nums[mid] > nums[left]:
return self.findMin(nums[mid + 1: ])
elif nums[mid] < nums[left]:
return self.findMin(nums[: mid + 1])
Here is a very simple answer, it will work for all test cases:
int a[] = {5,6,7,1,2,3,4};
int a[] = {1,2,3};
int a[] = {3,2,1};
int a[] = {3,1,2};
int a[] = {2,2,2,2};
public class FindSmallestNumberInSortedRotatedArray {
public static void main(String[] args) {
int a[] = { 4, 5, 6, 7, 1, 2, 3 };
int j = a.length - 1;
int i = 0;
while (i < j) {
int m = (i + j) / 2;
if (a[m] < a[m + 1] && a[m] < a[m - 1]) {
System.out.println(a[m] + "is smallest element ");
break;
} else if (a[m] > a[m + 1] && a[m - 1] > a[m + 1]) {
i = m + 1;
} else {
j = m - 1;
}
}
if (i == j)
System.out.println(a[i] + " is smallest element");
}
Solution for both array with duplicate and not, with the recursive binary search approach.
Unique array
var min = (A, l, h) => {
if(l >= h) return A[l];
let m = Math.floor((l + h) / 2);
// as its unique
if(A[m] > A[h]) {
// go towards right as last item is small than mid
return min(A, m + 1, h);
} else if(A[m] > A[m - 1]) {
// go towards left as prev item is smaller than current
return min(A, l, m - 1);
} else {
// right and left is greater than current
return A[m];
}
}
/**
* #param {number[]} nums
* #return {number}
*/
var findMin = function(nums) {
// If array is rotated nums.length time or same as it is
if(nums[0] < nums[nums.length - 1]) return nums[0];
return min(nums, 0, nums.length - 1);
};
Array with duplicates
var min = (A, l, h) => {
if(l >= h) return A[l];
// traverse from left "and right" to avoid duplicates in the end
while(A[l] == A[l+1]) {
l++;
}
let m = Math.floor((l + h) / 2);
// as its unique
if(A[m] > A[h]) {
// go towards right as last item is small than mid
return min(A, m + 1, h);
} else if(A[m] >= A[m - 1]) {
// go towards left as prev item is smaller than current
return min(A, l, m - 1);
} else {
// right and left is greater than current
return A[m];
}
}
/**
* #param {number[]} nums
* #return {number}
*/
var findMin = function(nums) {
// If array is rotated nums.length time or same as it is
if(nums[0] < nums[nums.length - 1]) return nums[0];
return min(nums, 0, nums.length - 1);
};
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);
}