Twitter Interview Question for Software Engineer / Developers


Country: United States
Interview Type: Phone Interview




Comment hidden because of low score. Click to expand.
3
of 3 vote

We can get down to O(n^2) worst case and no additional memory by using two pointers to scan the remainder of the array rather than searching for the missing element. I think we can do even better for a best case. However, duplicates are annoying. Your own example is confusing: you print both combinations of [3,0,-3] but you do not print all four combinations of [2,-2,0].

- Sir CodesALot April 19, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

That two-pointer idea is superb. Thanks for that.

- iroodaz April 19, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

The two pointer approach is a very common approach. This problem is a very common problem in interviews.

The idea was first used in connection with the general subset sum problem in the 1970s.

- Anonymous April 19, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Can someone explain to me how the two-pointer method is done? I didn't quite follow the hint.

- bobthrollop April 20, 2014 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 votes

great idea! +1

Here is an explanation for that:

(1). First look at an easier problem: Given a SORTED array, find 2 elements that sum up to some value, say S.

This can be done in O(n) using two pointer approach: using two pointers that point to the start (Pstart) and the end (Pend) of the sorted array.
Depends on whether the sum values of the two pointers is smaller of not smaller than S, we increase Pstart++ or decrease Pend--, respectively. This takes O(n) time, since the range is decreasing every step.
No extra space is needed.

(2). Now come back to the original problem with 3 elements:

First, sort the array. This takes O(n logn) with no extra space if using heap-sort.

For each element x in this array, do this sub-task: Find in the remaining SORTED array two elements that sum up to -x. This sub-task is done in O(n) as in (1).

Thus, the overall solution is O(n ^2) with no extra space.

- ninhnnsoc April 21, 2014 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 vote

import java.util.Arrays;
import java.util.HashSet;

public class CombinationOf3Numbers {

	public static void main(String[] args) {
		Integer[] inputList = { 2, 3, 1, -2, -1, 0, 2, -3, 0 };
		new CombinationOf3Numbers().findTheNumbers(inputList);
	}

	public void findTheNumbers(Integer[] inputList) {
		Arrays.sort(inputList);

		HashSet<Integer> m = new HashSet<Integer>();
		//O(n)
		for (int i = 0; i < inputList.length; i++) {
			m.add(inputList[i]);
		}

		HashSet<DS> map = new HashSet<DS>();

		for (int i = 0; i < inputList.length; i++) {
			for (int j = i; j < inputList.length; j++) {
				if (m.contains(-1 * (inputList[i] + inputList[j]))) {
					DS a = new DS();
					a.a[0] = inputList[i];
					a.a[1] = inputList[j];
					a.a[2] = -1 * (inputList[i] + inputList[j]);
					map.add(a);
				}
			}
		}

		for (DS ds : map) {
			System.out.println(ds);
		}

	}

	class DS {
		int[] a;

		public DS() {
			a = new int[3];
		}
		
		@Override
		public int hashCode() {
			return a[0]*1 + a[1]*1 + a[2]*2;
		}
		
		@Override
		public boolean equals(Object obj) {
			DS newInstance = (DS) obj;
			return this.a[0] == newInstance.a[0]
					&& this.a[1] == newInstance.a[1]
					&& this.a[2] == newInstance.a[2];
		}

		public String toString() {
			return a[0] + " , " + a[1] + ", " + a[2];
		}
	}

}

- Karthik August 07, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

Just sort the numbers. And then take any possible cominations for the 1st 2 numbers(say a , b). The 3rd one(c = 0 - (a+b)) can be found in logn time in the sorted list. So the complexity would be (n*n*logn)

- prd April 19, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

Correct solution! However we can have an O(n*n) solution using a hash table.

- iroodaz April 19, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 3 votes

Calculate the sums of any two numbers, and store them in an array of length O(n^2). This takes O(n*n).

Then for each element x in the original list, do a binary search for -x in the sum array. This takes O(n log(n^2)) = O(2nlogn) = O(nlogn).

Thus, the overall will take O(n^2).

EDITED: Above is wrong!
Should store the sums in a hash table, no binary search needed.

- ninhnnsoc April 19, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

A solution with quadratic running time.

1. Put negative of every number in a hash table with its index.
2. For every combination of two elements i and j (j>i) search for their sum in the hash table and print out i, j, and any index that is greater than j for their sum in the hash table.

A C++11 solution using STL vector and unordered_map (that is our hash table).

#include <iostream>
#include <unordered_map>
#include <vector>
#include <stdio.h>

using namespace std;

void solve(int *ary, int n)
{
	unordered_map <int, vector<int> > hashtable(10000);
	vector <int> tmp;
	tmp.push_back(0);
	for (int i = 0; i < n; i++)
	{
		auto x = hashtable.find(-1 * ary[i]);
		if (x != hashtable.end())
			x->second.push_back(i);
		else
		{
			tmp[0] = i;
			hashtable[-1 * ary[i]] = tmp;
		}
	}

	for (int i = 0; i < n; i++)
	{
		for (int j = i + 1; j < n; j++)
		{
			auto x = hashtable.find(ary[i] + ary[j]);
			if (x != hashtable.end())
			{
				for (auto y : x->second)
				{
					if (y>j)
						printf("%d: %d , %d: %d , %d: %d\n", i, ary[i], j, ary[j], y, ary[y]);
				}
			}
		}
	}
	
}

Love the way that auto does magic in C++11.

- iroodaz April 19, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Note that this problem is output-sensitive, that is if all elements are equal to 0 we cannot do better than O(n-cubed). Therefore, the algorithm's running time is max( O(n-squared) , O(K) ) where K denotes the output size.

- iroodaz April 19, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

// returns true if there is triplet with sum equal
// to 'sum' present in A[]. Also, prints the triplet
bool find3Numbers(int A[], int arr_size, int sum)
{
int l, r;

/* Sort the elements */
quickSort(A, 0, arr_size-1);

/* Now fix the first element one by one and find the
other two elements */
for (int i = 0; i < arr_size - 2; i++)
{

// To find the other two elements, start two index variables
// from two corners of the array and move them toward each
// other
l = i + 1; // index of the first element in the remaining elements
r = arr_size-1; // index of the last element
while (l < r)
{
if( A[i] + A[l] + A[r] == sum)
{
printf("Triplet is %d, %d, %d", A[i], A[l], A[r]);
return true;
}
else if (A[i] + A[l] + A[r] < sum)
l++;
else // A[i] + A[l] + A[r] > sum
r--;
}
}

// If we reach here, then no triplet was found
return false;
}

- Anonymous April 19, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

There could be multiple triplets.

- Anonymous June 18, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

There could be multiple triplets.

- Anonymous June 18, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here is my solution in Java:

package random;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class SumOfThreeEqualsZero {
	static void getSumZero(Integer[] nums) {
		HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
		for (int i = 0; i < nums.length; i++) {
			Integer key = nums[i];
			if (map.containsKey(key))
				map.put(key, map.get(key) + 1);
			else
				map.put(key, 1);
		}

		List<String> list = new ArrayList<String>();
		// to get just one permutation of (i, j k) we will assume i <= j <= k
		for (Integer i : map.keySet()) {
			for (Integer j : map.keySet()) {
				if (j >= i) {
					if (i == j && i == 0) {
						// i == j == k == 0 case
						int count_i = map.get(i);
						int count_i_choose_3 = count_i * (count_i - 1) * (count_i - 2) / 6;
						for (int m = 0; m < count_i_choose_3; m++) {
							list.add("[0, 0, 0]");
						}
					} else if (i == j) {
						// i == j < k case
						Integer k = -(i + j);
						if (k > j) {
							int count_i = map.get(i);
							int count_i_choose_2 = count_i * (count_i - 1) / 2;

							if (map.containsKey(k)) {
								int times = count_i_choose_2 * map.get(k);
								for (int m = 0; m < times; m++) {
									list.add("[" + i + ", " + j + ", " + k + "]");
								}
							}
						}
					} else if (j > i) {
						Integer k = -(i + j);
						if (k == j) {
							// i < j == k case
							int count_j = map.get(j);
							int count_j_choose_2 = count_j * (count_j - 1) / 2;
							int times = count_j_choose_2 * map.get(i);
							for (int m = 0; m < times; m++) {
								list.add("[" + i + ", " + j + ", " + k + "]");
							}
						} else if (k > j && map.containsKey(k)) {
							// i < j < k case
							int times = map.get(i) * map.get(j) * map.get(k);
							for (int m = 0; m < times; m++) {
								list.add("[" + i + ", " + j + ", " + k + "]");
							}
						}
					}
				}
			}
		}
		for (String str : list) {
			System.out.println(str);
		}
	}

	public static void main(String[] args) {
		Integer[] a = { 2, 3, 1, -2, -1, 0, 2, -3, 0 };
		getSumZero(a);
	}

}

- wilsonmarriel April 19, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Three numbers sum to zero in 2 cases:
1) Two -ve numbers and a +ve number sum to 0
2) Two +ve numbers and a -ve number sum to 0.

So, sort the array in ascending order, that gives subarrays of +ve and -ve numbers in sorted orders.

1. Then run a double for-loop, from the start, on the negative sub-array, and for this -ve tuple, look for the corresponding positive number(that sums up to 0) in the positive sub-array from the end.
2. Also run a double for-loop, from the end, on the positive sub-array, and for this +ve tuple,
look for the corresponding negative number(that sums up to 0) in the negative sub-array from the start.

Worst-case time complexity: O(n^2), Space complexity O(1)

- Murali Mohan April 19, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

How can you find the corresponding number in O(1) in the double loops? It's impossible if you want keep memory usage in O(1) (other than the input). If you use a hash set, then the space complexity would be O(n). Also you must take zeros into account (if you don't, your algorithm will output duplicate combinations). Actually there are four cases where three numbers sum to zero:

1. n + n + p = 0
2. n + p + p = 0
3. n + z + p = 0
4. z + z + z = 0

where n is for negative, p for positive and z for zero. The corrected algorithm would be as follows:

1. Sort the input in ascending order. O(nlogn)
2. Find the indexes where zeros and positive numbers start. O(n)
3. Make a hash set S for negative and positive numbers. It is used to test whether a number is in the input. O(n) for both time and space.
4. Run a double for-loop on negative numbers. For a pair of two negative numbers (a, b), find the corresponding positive number c such that c = -(a + b) using the hash set S. Print the three numbers (a, b, c) if such c is found. O(n^2)
5. Run a double for-loop on positive numbers in a way similar to 4. O(n^2)
6. If there is a zero in the input, run a single loop on negative numbers. For each negative number a, find a positive number b using the hash set S which has the same absolute value, i.e. b = -a. Print (a, b, 0) if such b is found. O(n)
7. If there are three or more zeros, print (0, 0, 0). O(1)

Overall: O(n^2) for time, O(n) for space

EDIT: it still can output duplicate combinations. The algorithm should be modified to handle separately numbers appearing only once and twice or more.

- lemonedo April 20, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Sort inputs first, the select first two a, b and then do the binary search to get the third one c with condition c=-(a+b). Java program as followed:

public void doCalculation(int a[]) {
		Arrays.sort(a);
		for (int i = 0; i < a.length; i++) {
			for (int j = i + 1; j < a.length; j++) {
				int k = Arrays.binarySearch(a, -(a[i] + a[j]));
				if (k > j)
					System.out.println(a[i] + " " + a[j] + " " + a[k]);
			}
		}
	}

- finalfanleisy April 19, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

This is a standard three sum problem.

- khunima April 20, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

ArrayList<int[]> FindSumOfThreeUnique(int[] arr)
{
	//sort the array
	Arrays.sort(arr);

	//unique value in order
	Set<Integer> set = new LinkedHashSet<Integer>(Arrays.asList(arr));	

	//FindSumOfThree
	return FindSumOfThree(set.toArray(),0);

}

ArrayList<int[]> FindSumOfThree(int[] arr, int sum)
{
	ArrayList<int[]> results = new ArrayList<int[]>();

	int i,j,k;

	for(i = 0; i<arr.length(); i++)
		for(j = 0; j<arr.length(); j++)
			for(k = 0; k<arr.length(); k++)

			if(arr[i]+arr[j]+arr[k] == sum)
			{
				results.add(new int[3]);
				results.get(result.size())[0] = arr[i];
				results.get(result.size())[1] = arr[j];
				results.get(result.size())[2] = arr[k];			
				
			}

	return results;

}

- mikezebin April 24, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

def find_zero_for_three(input)
	input.sort!
	input.each_with_index do |item, index|
		i_start = index + 1
		i_end = input.size - 1
		while i_start < i_end do
			if item * (-1) > input[i_start] + input[i_end]
				i_start += 1
			elsif item * (-1) < input[i_start] + input[i_end]
				i_end -= 1 
			else
				print [item, input[i_start], input[i_end]].join(",") + "\n"
				i_start += 1
			end
		end
	end
end

- Yelena June 13, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Solution: sort the input, then take the sum from the first and last element, try to find the opposite number in the list, if true, add the list, else move from tail of the list up to 0. After this, remove the first element, repeat process.

This has the assumption that first 2 and second 2 are different. Otherwise, needs to change list to set.

public class ZeroSum {

public List<List<Integer>> sumZero(List<Integer> input){
Collections.sort(input, Collections.reverseOrder());
List<List<Integer>> result = new ArrayList<List<Integer>>();
while(!input.isEmpty()){
int firstElement = input.get(0);
if(firstElement<=0) break;
int index = input.size()-1;
System.out.println("index is -> "+ index);
while(input.get(index)<0){
int twoSum = 0 - (firstElement + input.get(index));
if(input.contains(twoSum)) {
List<Integer> resultList = new ArrayList<Integer>();
resultList.add(firstElement);
resultList.add(input.get(index));
resultList.add(twoSum);
result.add(resultList);
}
index--;
}
input.remove(0);
}
return result;
}

}

- Hotech October 15, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

package com.mj.algo.misc;

public class ZeroSumCombination {
	
	void printCombinationZeroSum(int arr[], int n, int r)
	{
		int [] data= new int[r];
	 
	    // Print all combination using temprary array 'data[]'
	    combinationUtilZeroSum(arr, n, r, 0, data, 0);
	}
	
	void combinationUtil(int arr[], int n, int r, int index, int data[], int i)
	{	
		if(index == r){
			for(int pos = 0; pos<r; pos++){
				System.out.print(data[pos] + " ");
			}
			System.out.println();
			return;
		}
		
		if(i>=n){
			return;
		}
		data[index]=arr[i];
		
		// current is included, put next at next location
		combinationUtil(arr,n, r, index+1, data, i+1);
		
		// current is excluded, replace it with next (Note that
	    // i+1 is passed, but index is not changed)
		combinationUtil(arr,n, r, index, data, i+1);
		
	}

	void combinationUtilZeroSum(int arr[], int n, int r, int index, int data[], int i)
	{	
		if(index == r){
			if(checkSumtoZero(data)){
				System.out.println();
			}
			return;
		}
		
		if(i>=n){
			return;
		}
		data[index]=arr[i];
		
		// current is included, put next at next location
		combinationUtil(arr,n, r, index+1, data, i+1);
		
		// current is excluded, replace it with next (Note that
	    // i+1 is passed, but index is not changed)
		combinationUtil(arr,n, r, index, data, i+1);
		
	}
	
	private boolean checkSumtoZero(int[] input){
		if(input == null){
			return false;
		}
		int sum = 0;
		for(int index = 0; index<input.length; index++){
			sum = sum + input[index];
		}
		if(sum == 0){
			return true;
		}
		return false;
	}
	
	private void findSumToZero(int[] input){
		for(int index = 0; index<input.length; index++){
			printCombinationZeroSum(input, input.length, index);
		}
	}
	
	
	
	public static final void main(String args[]){
		ZeroSumCombination zeroSumCombination = new ZeroSumCombination();
		int[] input = {2, 3, 1, -2, -1, 0, 2, -3, 0};
		zeroSumCombination.findSumToZero(input);
	}

}

- Mritunjay Kumar September 02, 2015 | Flag Reply


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More