Trying to solve codility lessons for practice and working on this.
Written my code in Java and tested the code on a wide range of inputs, however the code fails for extreme_min_max, single and double in the codility test results.
Assumption given:
N is an integer within the range [1..100,000].
Each element of array A is an integer within the range [1..1,000,000,000].
Explanation of my code:
1. Sort the given array.
2. Iterate over each element in the array to find the difference between every consecutive pair. If the difference is not 1, Then its not a perm hence return 0. In case there is only one element in the array, return 1.
Can anyone please help me find out the bug(s) in my code?
My code:
public int solution(int[] A)
{
if(A.length == 1)
return 1;
Arrays.sort(A);
for (int i = 0; i < A.length-1; i++)
{
long diff = Math.abs(A[i] - A[i+1]);
if(diff!=1)
return 0;
}
return 1;
}
Here is simple and better implementation which runs in O(N) time complexity and takes O(N) space complexity.
public int solution(int[] A)
{
int size = A.length;
int hashArray[] = new int[size+1];
for (int i = 0; i < size; i++)
{
if(A[i]>size)
return 0;
else
hashArray[A[i]]+=1;
}
for(int i=1;i<=size;i++)
if(hashArray[i]!=1)
return 0;
return 1;
}
Try this in C# (Score 100%) :
using System;
using System.Linq;
class Solution {
public int solution(int[] A) {
if (A.Any(x => x == 0)) { return 0; }
var orderSelect = A.OrderBy(x => x).GroupBy(x => x);
if (orderSelect.Any(x => x.Count() > 1)) { return 0; }
var res = Enumerable.Range(1, A.Length).Except(A);
return res.Any() ? 0 : 1;
}
}
Pretty simple:
Your code doesn't check this condition:
A permutation is a sequence containing each element from 1 to N once, and only once.
Ensure that the first element after sorting is 1, and everything should work.
I'm not big on Java syntax, but what you want to do here is:
Create an array temp the length of A - initialized to 0.
Go over A and do temp[A[i]]++.
Go over temp, and if any place in the array is not 1, return false.
If duplicate exists - return 0 I have implemented with 100% pass
https://codility.com/demo/results/trainingWX2E92-ASF/
public static int permCheck(int A[]){
Set<Integer> bucket = new HashSet<Integer>();
int max = 0;
int sum=0;
for(int counter=0; counter<A.length; counter++){
if(max<A[counter]) max=A[counter];
if(bucket.add(A[counter])){
sum=sum+A[counter];
}
else{
return 0;
}
}
System.out.println(max+"->"+sum);
int expectedSum = (max*(max+1))/2;
if(expectedSum==sum)return 1;
return 0;
}
Here's my first 100% code.
I can't say if it's the fastest but it seems all correct -- watch the double OR ( || ) condition.
import java.util.Arrays;
class Solution
{
public int solution(int[] A)
{
int i = 0;
int size = A.length;
if ( size > 0 && size < 100001)
{
// Sort the array ascending:
Arrays.sort(A);
// Check each element:
for(i = 0; i < size; i++)
if ( A[i] > size || A[i] != (i + 1) )
return 0;
return 1;
}
return 0;
}
}
EDIT
Actually, we need not worry about valid first element data (i.e. A[i] > 0) because, after sorting, a valid perm array must have A[0] = 1 and this is already covered by the condition A[i] = i + 1.
The upper limit for array entries (> 1,000,000,000) is restricted further by the limit on the array size itself (100,000) and we must check for conformity here as there will be a Codility test for this. So I have removed the lower limit condition on array entries.
Below code runs and gave me a 100%, the time complexity is O(n):
private static int solution(int[] A) {
int isPermutation = 1; // all permutations start at 1
int n = A.length;
Arrays.sort(A);
if (n == 0) return 0; // takes care of edge case where an empty array is passed
for (int i = 0; i < n; i++) {
if (A[i] != isPermutation) { //if current array item is not equals to permutation, return 0;
return 0;
}
isPermutation++;
}
return 1;
}
100% score with complexity O(N)
public int solution(int[] A) {
int res = 1;
if (A.length == 1 && A[0]!=1)
return 0;
int[] B = new int[A.length];
for (int j : A) {
int p = j - 1;
if (A.length > p)
B[p] = j;
}
for (int i = 0; i < B.length - 1; i++) {
if (B[i] + 1 != B[i + 1]) {
res = 0;
break;
}
}
return res;
}
The question is about Solving this problem from codingBat in Java.
Problem Statement:
Return an array that contains the exact same numbers as the given array, but rearranged so that all the even numbers come before all the odd numbers. Other than that, the numbers can be in any order. You may modify and return the given array, or make a new array.
evenOdd({1, 0, 1, 0, 0, 1, 1}) → {0, 0, 0, 1, 1, 1, 1}
evenOdd({3, 3, 2}) → {2, 3, 3}
evenOdd({2, 2, 2}) → {2, 2, 2}
The Problem is simple with 2 loops I attempted at solving it with 1 it got too lengthy I believe, is there any other efficient way to solve the above problem using 1 loop?
do not use collections!
My solution:
public int[] evenOdd(int[] nums) {
boolean oddFound=false;
int count=-1;
int oddGap=0;
for(int i=0;i<nums.length;i++)
{
if(!(oddFound)&(nums[i]%2==0))
continue;
if((!oddFound)&(nums[i]%2==1))
{
oddFound=true;
count=i;
continue;
}
if((oddFound)&(nums[i]%2==1))
{
oddGap++;
continue;
}
if((oddFound)&(nums[i]%2==0))
{
int temp=nums[count];
nums[count]=nums[i];
nums[i]=temp;
if(i>0)
i--;
if(oddGap>0)
{
oddGap--;
count+=1;
oddFound=true;
continue;
}
oddFound=false;
}
}
return nums;
}
Since creating a new array is allowed, and the order of the numbers is irrelevant, I would use the following approach:
public int[] evenOdd(int[] nums) {
int[] output = new int[nums.length];
int evenPos = 0;
int oddPos = nums.length-1;
for (int i : nums) {
if (i%2==0) {
output[evenPos++]=i;
} else {
output[oddPos--]=i;
}
}
return output;
}
Update: A somewhat less readable version that doesn't require an extra array (along the lines of what #Seelenvirtuose suggests, just without the extra loops)
public int[] evenOdd(int[] nums) {
int evenPos = 0;
int oddPos = nums.length-1;
while (true) {
if (evenPos>=oddPos || evenPos>=nums.length || oddPos<0) {
break;
}
if (nums[evenPos]%2==0) {
evenPos++;
}
if (nums[oddPos]%2!=0) {
oddPos--;
}
if (evenPos<oddPos && nums[evenPos]%2 != 0 && nums[oddPos]%2 == 0) {
int tmp = nums[evenPos];
nums[evenPos] = nums[oddPos];
nums[oddPos] = tmp;
oddPos--;
evenPos++;
}
}
return nums;
}
You do not need any temporary lists or array because you can reorder the elements in-situ.
This is a simple algorithm:
Define two pointers, left and right (initially set to the bounds of the array).
As long as left does not exceed right and nums[left] is even, increment left.
As long as right does not exceed left and nums[right] is odd, decrement right.
If left is still less than right, swap the elements at positions left and right.
Repeat 2,3,4 as long as left is still less than right.
Got it? Here some code:
public int[] evenOdd(int[] nums) {
// (1)
int left = 0;
int right = nums.length -1;
do {
// (2)
while (left < right && nums[left] % 2 == 0)
left += 1;
// (3)
while (right > left && nums[right] % 2 != 0)
right -= 1;
// (4)
if (left < right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
} while (left < right); // (5)
return nums;
}
Okay! I finally jumped across this question which is actually closed but the solution by asker was almost there apart from failing in 2 cases which I fixed:
I commented out he code by asker which was making it fail in a couple of cases as seen in the question.
I think below is the simplest and most optimized solution:
public int[] evenOdd(int[] nums) {
int y=nums.length,x,a=0;
int temp=0;
for(x=0;x<y;x++)
{
if(nums[x]%2==0) {
if(a>(y-2))
return nums;
else{
//nums[a]=nums[a]+nums[x];
//nums[x]=nums[a]-nums[x];
//nums[a]=nums[a]-nums[x];
temp=nums[a];
nums[a]=nums[x];
nums[x]=temp;
a+=1;
}
}
return nums;
}
Traverse evenOdd from 0 to N.
for every even number encountered, copy it to the required position on the evenOdd array.
for every odd num encountered, store it in a separate array called oddnum.
After traversing the whole array, just copy the elements from oddnum to the Back of evenOdd.
Ex: evenOdd = {5,2,1,4}
Step 1. copy 5 to oddnum[0]
2. copy 2 to evenodd[0]
3. copy 1 to oddnum[1]
4. copy 1 to evenodd[1]
5. cpy oddnum[0] to evenOdd[2] and oddnum[1] to evenOdd[3]
Keeping to your restrictions, here's a one-loop answer:
public int[] evenOdd(int[] nums) {
int[] result = new int[nums.length];
int nextEven = 0;
int nextOdd = nums.length - 1;
for ( int num : nums )
{
if ( num % 2 == 0 )
result[ nextEven++ ] = num;
else
result[ nextOdd-- ] = num;
}
return result;
}
public int[] evenOdd(int[] nums) {
int count = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] % 2 == 0) {
int temp = nums[i];
nums[i] = nums[count];
nums[count] = temp;
count++;
}
}
return nums;
}
public int[] evenOdd(int[] nums) {
Stack stack = new Stack();
int[] nums2 = new int[nums.length];
for(int i = 0; i < nums.length; i++) {
if(nums[i] % 2 != 0) {
stack.push(nums[i]);
}
}
for(int i = 0; i < nums.length; i++) {
if(nums[i] % 2 == 0) {
stack.push(nums[i]);
}
}
for(int i = 0; i < nums.length; i++) {
nums2[i] = (Integer) stack.pop();
}
return nums2;
}
In-place version (stable):
We continually search for te first and last invalid values (first odd, before last even) and keep swapping them until they cross:
public int[] evenOdd(int[] nums) {
int first = 0, last = nums.length - 1;
while (first < last) {
while ((first < last) && isOdd(nums[last])) last--;
while ((first < last) && !isOdd(nums[first])) first++;
swap(nums, first, last);
}
return nums;
}
boolean isOdd(int num) { return (num & 1) == 1; }
void swap(int[] nums, int i, int j) {
int copy = nums[i];
nums[i] = nums[j];
nums[j] = copy;
}
With auxiliaries (stable):
We partition the even and odd values in separate lists and concatenate them back:
public int[] evenOdd(int[] nums) {
List<Integer> evens = new ArrayList<Integer>(nums.length);
List<Integer> odds = new ArrayList<Integer>(nums.length);
for (int num : nums)
if (isOdd(num)) odds.add(num);
else evens.add(num);
int[] results = new int[nums.length];
int i = 0;
for (int num : evens) results[i++] = num;
for (int num : odds) results[i++] = num;
return results;
}
boolean isOdd(int num) { return (num & 1) == 1; }
Simplified solution which uses Srteam API:
public int[] evenOdd(int[] nums) {
int[] evenOddArr = new int[nums.length];;
int[] evenArr = Arrays.stream(nums).filter(x -> x % 2 == 0).toArray();;
int[] oddArr = Arrays.stream(nums).filter(x -> x % 2 != 0).toArray();
evenOddArr = java.util.stream.IntStream.concat(Arrays.stream(evenArr), Arrays.stream(oddArr))
.toArray();
return evenOddArr;
}
It passes all the tests on CodingBat:
I'm having trouble combining these two algorithms together. I've been asked to modify Binary Search to return the index that an element should be inserted into an array. I've been then asked to implement a Binary Insertion Sort that uses my Binary Search to sort an array of randomly generated ints.
My Binary Search works the way it's supposed to, returning the correct index whenever I test it alone. I wrote out Binary Insertion Sort to get a feel for how it works, and got that to work as well. As soon as I combine the two together, it breaks. I know I'm implementing them incorrectly together, but I'm not sure where my problem lays.
Here's what I've got:
public class Assignment3
{
public static void main(String[] args)
{
int[] binary = { 1, 7, 4, 9, 10, 2, 6, 12, 3, 8, 5 };
ModifiedBinaryInsertionSort(binary);
}
static int ModifiedBinarySearch(int[] theArray, int theElement)
{
int leftIndex = 0;
int rightIndex = theArray.length - 1;
int middleIndex = 0;
while(leftIndex <= rightIndex)
{
middleIndex = (leftIndex + rightIndex) / 2;
if (theElement == theArray[middleIndex])
return middleIndex;
else if (theElement < theArray[middleIndex])
rightIndex = middleIndex - 1;
else
leftIndex = middleIndex + 1;
}
return middleIndex - 1;
}
static void ModifiedBinaryInsertionSort(int[] theArray)
{
int i = 0;
int[] returnArray = new int[theArray.length + 1];
for(i = 0; i < theArray.length; i++)
{
returnArray[ModifiedBinarySearch(theArray, theArray[i])] = theArray[i];
}
for(i = 0; i < theArray.length; i++)
{
System.out.print(returnArray[i] + " ");
}
}
}
The return value I get for this when I run it is 1 0 0 0 0 2 0 0 3 5 12. Any suggestions?
UPDATE: updated ModifiedBinaryInsertionSort
static void ModifiedBinaryInsertionSort(int[] theArray)
{
int index = 0;
int element = 0;
int[] returnArray = new int[theArray.length];
for (int i = 1; i < theArray.lenght - 1; i++)
{
element = theArray[i];
index = ModifiedBinarySearch(theArray, 0, i, element);
returnArray[i] = element;
while (index >= 0 && theArray[index] > element)
{
theArray[index + 1] = theArray[index];
index = index - 1;
}
returnArray[index + 1] = element;
}
}
Here is my method to sort an array of integers using binary search.
It modifies the array that is passed as argument.
public static void binaryInsertionSort(int[] a) {
if (a.length < 2)
return;
for (int i = 1; i < a.length; i++) {
int lowIndex = 0;
int highIndex = i;
int b = a[i];
//while loop for binary search
while(lowIndex < highIndex) {
int middle = lowIndex + (highIndex - lowIndex)/2; //avoid int overflow
if (b >= a[middle]) {
lowIndex = middle+1;
}
else {
highIndex = middle;
}
}
//replace elements of array
System.arraycopy(a, lowIndex, a, lowIndex+1, i-lowIndex);
a[lowIndex] = b;
}
}
How an insertion sort works is, it creates a new empty array B and, for each element in the unsorted array A, it binary searches into the section of B that has been built so far (From left to right), shifts all elements to the right of the location in B it choose one right and inserts the element in. So you are building up an at-all-times sorted array in B until it is the full size of B and contains everything in A.
Two things:
One, the binary search should be able to take an int startOfArray and an int endOfArray, and it will only binary search between those two points. This allows you to make it consider only the part of array B that is actually the sorted array.
Two, before inserting, you must move all elements one to the right before inserting into the gap you've made.
I realize this is old, but the answer to the question is that, perhaps a little unintuitively, "Middleindex - 1" will not be your insertion index in all cases.
If you run through a few cases on paper the problem should become apparent.
I have an extension method that solves this problem. To apply it to your situation, you would iterate through the existing list, inserting into an empty starting list.
public static void BinaryInsert<TItem, TKey>(this IList<TItem> list, TItem item, Func<TItem, TKey> sortfFunc)
where TKey : IComparable
{
if (list == null)
throw new ArgumentNullException("list");
int min = 0;
int max = list.Count - 1;
int index = 0;
TKey insertKey = sortfFunc(item);
while (min <= max)
{
index = (max + min) >> 1;
TItem value = list[index];
TKey compKey = sortfFunc(value);
int result = compKey.CompareTo(insertKey);
if (result == 0)
break;
if (result > 0)
max = index - 1;
else
min = index + 1;
}
if (index <= 0)
index = 0;
else if (index >= list.Count)
index = list.Count;
else
if (sortfFunc(list[index]).CompareTo(insertKey) < 0)
++index;
list.Insert(index, item);
}
Dude, I think you have some serious problem with your code. Unfortunately, you are missing the fruit (logic) of this algorithm. Your divine goal here is to get the index first, insertion is a cake walk, but index needs some sweat. Please don't see this algorithm unless you gave your best and desperate for it. Never give up, you already know the logic, your goal is to find it in you. Please let me know for any mistakes, discrepancies etc. Happy coding!!
public class Insertion {
private int[] a;
int n;
int c;
public Insertion()
{
a = new int[10];
n=0;
}
int find(int key)
{
int lowerbound = 0;
int upperbound = n-1;
while(true)
{
c = (lowerbound + upperbound)/2;
if(n==0)
return 0;
if(lowerbound>=upperbound)
{
if(a[c]<key)
return c++;
else
return c;
}
if(a[c]>key && a[c-1]<key)
return c;
else if (a[c]<key && a[c+1]>key)
return c++;
else
{
if(a[c]>key)
upperbound = c-1;
else
lowerbound = c+1;
}
}
}
void insert(int key)
{
find(key);
for(int k=n;k>c;k--)
{
a[k]=a[k-1];
}
a[c]=key;
n++;
}
void display()
{
for(int i=0;i<10;i++)
{
System.out.println(a[i]);
}
}
public static void main(String[] args)
{
Insertion i=new Insertion();
i.insert(56);
i.insert(1);
i.insert(78);
i.insert(3);
i.insert(4);
i.insert(200);
i.insert(6);
i.insert(7);
i.insert(1000);
i.insert(9);
i.display();
}
}
import java.util.*;
public class FirstOddOccurrence {
public static void main(String[] args) {
int[] x = {2, 4, 6, 7, 4, 3, 2, 7, 6, 7, 7};
int i;
display(x);
System.out.printf("# Occurrences of first odd = %3d\n", firstOddCount(x));
}
private static void display(int[] x) {
int i;
System.out.print("Array: ");
for (i = 0; i < x.length; i++) {
if (i < x.length - 1)
System.out.printf("%3d, ", x[i]);
else
System.out.printf("%3d\n", x[i]);
}
}
public static int odd(int[] x) {
int i;
int y;
for (i = 0; i < x.length; i++) {
y = x[i] % 2;
if (y == 1) {
return x[i];
} else {
return 0;
}
}
return x[i];
}
public static int firstOddCount(int x[]) {
int i;
int c = 0;
for (i = 0; i < x.length; i++) {
if (x[i] == odd(x))
c++;
}
return c;
}
}
I'm trying to find the first occurrence of an odd number in the array that has been provided. What is wrong with my program? I can't seem to get the program to count the first odd occurrences.
Your code here:
if (y == 1) {
return x[i];
} else {
return 0;
}
does not work - if a tested number is even, you immediately return 0. Instead you want to skip these even numbers and wait until an odd number comes up. In the end, if you don't find any odd number, you return 0. Here is the corrected version of odd():
int i;
int y;
for (i = 0; i < x.length; i++) {
y = x[i] % 2;
if (y == 1) {
return x[i];
}
}
return 0;
Andr's solution fixes your issue; odd(x) will return 0 if x[0] is even, and x[0] if it is odd.
You could also improve firstOddCount like so: odd(x) will always return the same value, so only calculate it once.
public static int firstOddCount(int x[]) {
int firstOdd = odd(x);
int c=0;
for(int i=0; i < x.length; i++) {
if (x[i]==firstOdd)
c++;
}
return c;
}
Your particular problem is that you return 0 if you find an even number. That means that the list {2, 4, 6, 8, 1} will give you 0, rather than 1, as the first odd number.
What you should do is ignore leading even numbers and continue to process the list.
However, the way you've organised your program, you're processing the first all-even part of the list twice, once in odd() to find the first odd number, then again in firstOddCount() to count how many of that number there are - that's totally unnecessary.
Once you find the first odd number, I think you can be reasonably certain that number (or any other odd number for that matter) does not exist in the space you've already searched. Otherwise it would have been the first odd number. Hence it makes little sense to go back and look at that initial part of the list again.
A way in which you can easily just process the list once is as follows:
public static int firstOddCount (int numbers[]) {
// Find first odd number or end of list.
int idx = 0, len = numbers.length;
while ((idx < len) && ((numbers[idx] % 2) == 0)
idx++;
// If at end of list, everything is even => count(first(odd)) is 0.
if (idx == len)
return 0;
// Otherwise, start counting from current position.
int count = 1, oddnum = numbers[idx];
while (++idx < len)
if (numbers[idx] == oddnum)
count++;
return count;
}
If you are trying to get one element from group you should use 'break' when your condition matched first time else it will give all...
I felt like doing an algorithm and found this problem on leetcode
Given an array of integers, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
My solution is O(n^2). I wanted to know if there is better way of doing this? like O(n) or O(nlogn)
import java.util.Arrays;
public class ReturnIndex {
public int[] twoSum(int[] numbers, int target) {
int tail = numbers.length-1;
int[] n = new int[2];
for (int i=0;i<tail;i++) {
for(int j=i+1;j<tail;j++) {
if(target ==(numbers[i]+numbers[j])) {
n[0] = i+1;
n[1] = j+1;
}
}
}
return n;
}
public static void main(String[] args) {
int[] s = {150,24,79,50,88,345,3};
int value = 200;
ReturnIndex r = new ReturnIndex();
int[] a = r.twoSum(s,value);
System.out.println(Arrays.toString(a));
}
}
Sort the array. Make two pointers point at first and last (x and X). Run this in a loop:
if (a[X]+a[x] > N) then X--
else if (a[X]+a[x] < N) then x++
else if (a[X]+a[x] == N) then found.
if (x > X) then no numbers exist.
O(nlogn) time, O(1) memory
O(n log n) time, O(1) memory (not counting the list):
First, sort the list. This should take O(n log n) time, as most sort functions do.
Iterate through the list, which should take O(n) time in the outer loop. At this point you can do a binary search for the closest matching integer in a sorted sublist, which should take O(log n) time. This stage should wind up taking O(n log n) total.
Edit: Check out Max's answer below. It's still O(n log n) time and O(1) memory, but he avoids the binary searches by walking a pointer from each end of the list.
O(n) time, O(n) memory:
Build a hash table, which should have O(1) insertion and O(1) contains. Then, in a O(n) outer loop, for each number i, check if total - i is in the hash table. If not, add it; if so, then you've got your two numbers.
Either way, you would need an additional scan through the array to get the indices, but that's no problem--it only takes O(n) time. If you wanted to avoid it you could keep the original index in the sorted list or hash table as needed, but that has a memory footprint instead of a time footprint.
Below you can find a solution in which the two numbers could be found in O(n log n) time:
1- Sort the numbers in ascending (or descending) order // O(n log n)
2- Compute diff = target - item for each item // O(n)
3- For each calculated diff, look up the calculated value in the sorted items
using the Binary search algorithm // O(n log n)
A complete, working implementation in Java:
import java.util.ArrayList;
public class NumbersFinder {
class Item{
private int value;
private int index;
public Item(int value, int index){
this.value = value;
this.index = index;
}
public int getValue(){
return value;
}
public int getIndex(){
return index;
}
}
public ArrayList<Item> find(int[] values, int target){
ArrayList<Item> items = new ArrayList<Item>();
for(int i = 0; i < values.length; i++)
items.add(new Item(values[i], i));
items = quicksort(items);
ArrayList<Integer> diffs = computeDiffs(items, target);
Item item1 = null;
Item item2 = null;
boolean found = false;
for(int i = 0; i < diffs.get(i) && !found; i++){
item1 = items.get(i);
item2 = searchSortedItems(items, diffs.get(i), 0, items.size());
found = item2 != null;
}
if(found){
ArrayList<Item> result = new ArrayList<Item>();
result.add(item1);
result.add(item2);
return result;
}
else
return null;
}
// find "value" in the sorted array of "items" using Binary search in O(log n)
private Item searchSortedItems(ArrayList<Item> items, Integer value, int lower, int upper) {
if(lower > upper)
return null;
int middle = (lower + upper)/2;
Item middleItem = items.get(middle);
if(middleItem.getValue() == value)
return middleItem;
else if(middleItem.getValue() < value)
return searchSortedItems(items, value, middle+1, upper);
else
return searchSortedItems(items, value, lower, middle-1);
}
// Simply calculates difference between the target value and each item in the array; O(n)
private ArrayList<Integer> computeDiffs(ArrayList<Item> items, int target) {
ArrayList<Integer> diffs = new ArrayList<Integer>();
for(int i = 0; i < items.size(); i++)
diffs.add(target - items.get(i).getValue());
return diffs;
}
// Sorts items using QuickSort algorithm in O(n Log n)
private ArrayList<Item> quicksort(ArrayList<Item> items) {
if (items.size() <= 1)
return items;
int pivot = items.size() / 2;
ArrayList<Item> lesser = new ArrayList<Item>();
ArrayList<Item> greater = new ArrayList<Item>();
int sameAsPivot = 0;
for (Item item : items) {
if (item.getValue() > items.get(pivot).getValue())
greater.add(item);
else if (item.getValue() < items.get(pivot).getValue())
lesser.add(item);
else
sameAsPivot++;
}
lesser = quicksort(lesser);
for (int i = 0; i < sameAsPivot; i++)
lesser.add(items.get(pivot));
greater = quicksort(greater);
ArrayList<Item> sorted = new ArrayList<Item>();
for (Item item : lesser)
sorted.add(item);
for (Item item: greater)
sorted.add(item);
return sorted;
}
public static void main(String[] args){
int[] s = {150,24,79,50,88,345,3};
int value = 200;
NumbersFinder finder = new NumbersFinder();
ArrayList<Item> numbers = finder.find(s, value);
if(numbers != null){
System.out.println("First Number Found = " + numbers.get(0).getValue() + " ; Index = " + + numbers.get(0).getIndex());
System.out.println("Second Number Found = " + numbers.get(1).getValue() + " ; Index = " + + numbers.get(1).getIndex());
}
else{
System.out.println("No such two numbers found in the array!");
}
}
}
Output:
First Number Found = 50 ; Index = 3
Second Number Found = 150 ; Index = 0
One line solution in python :
class Solution(object):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
def twoSum(self, nums, target):
x = [[i, nums.index(target-j)] for i,j in enumerate(nums) if nums.count(target-j) > 0 and nums.index(target-j)!=i]
return x.pop()
Can provide an O(n) time solution, but his memory cannot be O(1)
First you declare a key-value pair , where key is the value in the array of integers and value is the index in the array of integers. And, you need to declare a hash table to hold the key-value pairs.
Then you need to iterate through the entire array of integers,
if the value of this array (=sum - array[i]) is in the hash table, congratulations you found it,
if not, it is stored in the hash table.
So the entire time spent is the time to insert and query the hash table.
Memory is the size of the hash table.
My English is not very good, I hope I can help you.
public static void main(String args[]) {
int[] array = {150,24,79,50,88,345,3};
int sum = 200;
Map<Integer,Integer> table = new HashMap<>();
StringBuilder builder = new StringBuilder();
for(int i=0;i<array.length;i++){
int key = sum - array[i];
if(table.containsKey(key)){
builder.append("index1=").append(table.get(key)).
append(" index2=").append(i);
}else{
table.put(array[i],i);
}
}
System.out.println(builder);
}
As #Prayer mentioned above, here is the accepted answer.
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] resultarray=new int[2];
for (int i=0;i<nums.length-1;i++){
for(int k=i+1;k<nums.length;k++)
{
if(target==nums[i]+nums[k])
{
resultarray[0]=i;
resultarray[1]=k;
}
}
}
return resultarray;
}
}
The naïve solution to the two-sum problem is O(n^2), s.t. n is the length of the array of numbers provided.
However, we can do better by using a hash-map of the values seen so far (key=number, value=index) and checking if the complement is already there (O(1)) as we iterate over the numbers. This approach is optimal for an unsorted array:
Runtime complexity: O(n)
Space complexity: O(n) -- though if there is a solution, in practice this would be O(n/2)
Given the OP's question:
does not specify whether the input array is sorted or not (it is, therefore, safe to assume the input array can be anything), and
specifically asks for indexes of the provided array, as opposed to the actual numbers, any kind of solution sorting the array would need to copy it beforehand, keep a mapping of indexes between the sorted array and the unsorted one, or iterate over the original array, hence costing memory (O(n)) or time (O(n)), depending on the approach chosen. Therefore, the 1st part of the (currently) accepted solution is, strictly speaking, incorrect.
Optimal solution:
In Python:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
seen = {}
for j, num in enumerate(nums):
i = seen.get(target-num, -1)
if i != -1:
return [i+1, j+1]
seen[num] = j
return [-1, -1]
In Java:
import java.util.Map;
import java.util.HashMap;
public class Solution {
public int[] twoSum(int[] nums, int target) {
final Map<Integer, Integer> seen = new HashMap<>();
for (int j = 0; j < nums.length; ++j) {
final Integer i = seen.get(target - nums[j]); // One hash-map access v.s. two when using contains beforehand.
if (i != null) {
return new int[]{ i+1, j+1 };
}
numbers.put(nums[j], j);
}
return new int[]{-1, -1};
}
}
Note that by construction, if the complement is present in the map/dictionary, then the index stored will always be lower than the current index. Hence the following proposition is verified:
index1 must be less than index2
Also note that the OP's question needed 1-based indexes, which is what I've provided above, but the Leetcode question referred to seems to have been updated since then, and now is 0-based: https://leetcode.com/problems/two-sum.
I hope this helps.
Here is an O(n):
public int[] findSumMatched(int[] numbers, int target) {
Map<Integer, Integer> mapOfNumbers = new HashMap<Integer, Integer>();
for (int i = 0; i<numbers.length; i++) {
int secondNumber = target - numbers[i];
if (mapOfNumbers.get(secondNumber) != null){
return new int[] {mapOfNumbers.get(secondNumber), i};
}
mapOfNumbers.put(numbers[i], i);
}
throw new IllegalArgumentException();
}
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
out_list=[]
for i in range(len(nums)):
for j in range(len(nums)):
if(target-nums[i]) == nums[j] and i != j:
out_list.append(i)
return out_list
I would approach it this way:
Order your array from smaller to lower value
Loop over your array the way you have it but exit the loop early whenever
target <(numbers[i]+numbers[j])
Once you have the value of your two elements such that n[0] + n[1] = target, look back at the original array to find their index.
Here is my cpp solution with O(nlog(n)):
vector<int> two_sum(vector<int> &numbers, int target) {
vector<int> result;
vector<int> numbers_dup = vector<int>(numbers);
sort(numbers_dup.begin(), numbers_dup.end());
int left = 0, right = numbers_dup.size() - 1;
while(left <= right) {
int sum = numbers_dup[left] + numbers_dup[right];
if(sum == target) {
//find the idex of numbers_dup[left] and numbers_dup[right]
for(int i = 0; i < numbers.size(); i++) {
if(numbers[i] == numbers_dup[left] || numbers[i] == numbers_dup[right]) {
result.push_back(i);
}
if(result.size() == 2) {
return result;
}
}
}
else if(sum > target) {
right--;
}
else {
left++;
}
}
}
Check out my blog for the detailed explanation.
https://algorithm.pingzhang.io/Array/two_sum_problem.html
Here is the answer using HashMap in java with two passes of the array. Assuming that there are no duplicate elements in the array and there is exactly one solution exists.
import java.util.HashMap;
public class TwoSum {
int[] index = new int[2];
public int[] twoSum(int[] nums, int target)
{
int length = nums.length;
//initialize return values assuming that pair for the given target
//doesn't exist
index[0]=-1;
index[1]=-1;
//sanity check
if(length<1) return index;
HashMap<Integer, Integer> numHash = new HashMap<>(length);
//get the values from array into HashMap assuming that there aren't duplicate values
for(int i=0; i<length;i++)
{
numHash.put(nums[i],i);
}
//check for the value in the array and the difference between target and it. Assume that only
//one such pair exists
for(int i=0;i<length;i++)
{
int val1 = nums[i];
int val2=target-val1;
//make sure that it doesn't return the index of the first number in the pait you are searching for
if( numHash.containsKey(val2) && numHash.get(val2)!=i){
index[0]=i;
index[1] =numHash.get(target-nums[i]);
break;
}
}
return index;
}
}
public static int[] twoSum(int[] nums, int target) {
int []resultarray=new int[2];
for (int i=0;i<nums.length-1;i++){
for(int k=1;k<nums.length;k++)
{
if(target==nums[i]+nums[k])
{
resultarray[0]=nums[i];
resultarray[1]=nums[k];
}
}
}
return resultarray;
}
This is my python solution
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
copy_dict = {}
for pos in range(0, len(nums)):
if nums[pos] not in copy_dict.keys():
copy_dict[nums[pos]] = [pos]
else:
copy_dict[nums[pos]].append(pos)
def get_sum_indexes(sorted_array, target):
right_pointer = len(sorted_array) - 1
left_pointer = 0
while left_pointer < len(sorted_array) or right_pointer > 0:
if sorted_array[right_pointer] + sorted_array[left_pointer] == target:
return [sorted_array[left_pointer], sorted_array[right_pointer]]
elif sorted_array[right_pointer] + sorted_array[left_pointer] > target:
right_pointer -= 1
elif sorted_array[right_pointer] + sorted_array[left_pointer] < target:
left_pointer += 1
return None
sum_numbers = get_sum_indexes(sorted(nums), target)
if len(copy_dict[sum_numbers[0]]) == 1:
answer_1 = copy_dict[sum_numbers[0]][0]
else:
answer_1 = copy_dict[sum_numbers[0]][0]
if len(copy_dict[sum_numbers[1]]) == 1:
answer_2 = copy_dict[sum_numbers[1]][0]
else:
answer_2 = copy_dict[sum_numbers[1]][1]
return sorted([answer_1, answer_2])
print(Solution().twoSum(nums=[-1, -2, -3, -4, -5], target=-8))
print(Solution().twoSum(nums=[-3, -3], target=-6))
Sort the list in non-decreasing order. It takes O(nlogn) time complexity.
Find the two numbers, which can be done in O(n) time.
Find the two indices of the two numbers, which can be done in O(n) time.
Overall complexity is O(nlogn).
Implementation in python:
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
p = nums[:]
p.sort() #sorting in -> O(nlogn)
r = len(nums)-1
l =0
#find the indices -> O(n)
for i in range(len(nums)):
if(p[l] + p[r]<target):
l += 1
elif (p[l] + p[r]>target):
r -=1
else :
first_num = p[l]
second_num = p[r]
#find the indices of the numbers -> O(n)
for i in range(len(nums)):
if(nums[i]==first_num):
first_index = i
elif (nums[i]==second_num):
second_index = i
return [first_index,second_index]
Swift code with Time Complexity O(n) and Space complexity O(n):
import UIKit
class Solution{
func twoSum(_ nums: [Int], _ target: Int) -> [Int]{
var finalArray = [Int]()
var newDictionary = [Int:Int]()
for i in 0..<nums.count{
let complement = target - nums[i]
if newDictionary[complement] != nil && newDictionary[complement] != i{
finalArray.append(newDictionary[complement]!)
finalArray.append(i)
return finalArray
}
newDictionary[nums[i]] = i
}
return []
}
}
func main(){
let solution = Solution()
print("All Good" ,solution.twoSum([1, 3, 4 , 5], 6))
}
main()
An O(n) solution in c++ using hash map only exploiting Commutative rule of Addition in real numbers.
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> my_map;
for ( int i = 0 ; i < nums.size(); i++ ){
if(my_map.find(target - nums[i]) != my_map.end()){
return vector<int> {my_map[target - nums[i]], i};
}
my_map[nums[i]] = i ;
}
}
};
I tried most of the answers and they don't seem to handle the edge cases properly. Hence, throwing my two cents for python3 solution that handles the edge cases. I used Max's algorithm to implement it:
def twoSum(nums, target):
output=[]
arr=sorted(nums)
x=0
y=-1
X=len(nums)-1
while x<X:
if (arr[X]+arr[x] > target):
X-=1
elif (arr[X]+arr[x] < target):
x+=1
elif (arr[X]+arr[x] == target):
#print("Found",arr[X],arr[x])
num1=arr[x]
num2=arr[X]
x+=1
X-=1
for i in range(len(nums)):
if num1 == nums[i] and y==-1:
index1=i
y=i
elif num2 == nums[i]:
index2=i
return [index1, index2]
N.B. It's important to consider edge cases and inputs like the following
print(twoSum([3,2,4], 6)) # [1,2]
print(twoSum([3,3], 6)) # [0,1]
Here is an Efficient Solution.
Time Complexity - O(n) and Space Complexity - O(1)
Sol: Will take two-pointer(start_pointer and end_pointer). Initially start_pointer point at the first index and end_pointer point to the last.
Add both the element (sum = array[start_pointer] + array[last_pointer]. After that check, if the sum > target element or not. If yes decrease the end_pointer else increase start_pointer. If sum = target, means you got the indexes.
public int[] twoSum(int[] numbers, int target) {
int[] arr = new int[2]; // to store result
int sum=0;
int start_pointer=0;
int end_pointer = (numbers.length)-1;
while(start_pointer<=end_pointer){
sum=numbers[start_pointer]+numbers[end_pointer];
if(sum>target)
end_pointer-=1;
else if(sum<target)
start_pointer+=1;
else{
arr[0]=start_pointer;
arr[1]=end_pointer;
break;
}
}
return arr;
}
We can do with HashMap and the time complexity would be O(n)
public class ReturnIndicesOfElementsAddToSum {
public static void main(String[] args) {
int[] nums = {2, 7, 11, 15};
int target = 18;
if(!getIndices(nums,target)) {
System.out.println("No such numbers found");
}
}
static boolean getIndices(int[] nums, int target) {
Map<Integer,Integer> indexMap = new HashMap<>();
boolean numFound = false;
for(int i=0;i<nums.length;i++) {
int temp = target - nums[i];
indexMap.put(nums[i], i);
if(indexMap.containsKey(temp)) {
System.out.printf("%d and %d adds upto the target value and indices are %d and %d"
, nums[i], temp, i, indexMap.get(temp));
numFound = true;
}
}
return numFound;
}
}
Using HashMap this is also a solution if complexity for search in HashMap will in order of O(logn) then in worst case the complexity will be O(nlogn)
public int[] twoSum(int[] nums, int target) {
int [] resultIndex = null;
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int i=0;i<nums.length;i++){
int temp = target - nums[i];
if(map.containsKey(temp)){
resultIndex = new int[2];
resultIndex[0]=map.get(temp);
resultIndex[1]=i;
}else{
map.put(nums[i],i);
}
}
return resultIndex;
}
Just curious, but what's wrong with this O(n) solution?
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length - 1; i++){
if (nums[i] + nums[i+1] == target)
return new int[] {i, i+1};
}
return null;
}
My solution to this problem would be,
public int[] twoSums(int[] unsortedNum, int target) {
int[] nums = Arrays.copyOf(unsortedNum, unsortedNum.length);
Arrays.sort(nums);
boolean isResultFound = false;
int start = 0;
int end = nums.length-1;
while(!(start > end)) {
if(nums[start]+nums[end] > target){
end--;
} else if (nums[start]+nums[end] < target){
start++;
} else if(nums[start] + nums[end] == target){
isResultFound = true;
break;
}
}
if(isResultFound){
int s = -1;
int e = -1;
for(int i = 0; i< unsortedNum.length; i++){
if(s != -1 && e != -1){
break;
}
if(s == -1 && unsortedNum[i] == nums[start]){
s = i;
} else if(e == -1 && unsortedNum[i] == nums[end]) {
e = i;
}
}
return new int[] {s,e};
}
// for element not found
return new int[]{-1,-1};
}
In the end, if you get -1, -1 as the index then you can say that elements not found which could sum to the target element.
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] sortedNums = Arrays.copyOf(nums, nums.length);
Arrays.sort(sortedNums);
int leftSortedIndex = 0;
int rightSortedIndex = sortedNums.length - 1;
while(leftSortedIndex < rightSortedIndex) {
int sum = sortedNums[leftSortedIndex] + sortedNums[rightSortedIndex];
if(sum == target) {
break;
} else if(sum < target) {
leftSortedIndex++;
} else {
rightSortedIndex--;
}
}
int leftIndex = -1;
int rightIndex = -1;
for(int index=0; index < nums.length; index++) {
if(leftIndex == -1 && nums[index] == sortedNums[leftSortedIndex]) {
leftIndex = index;
continue;
}
if(rightIndex == -1 && nums[index] == sortedNums[rightSortedIndex]) {
rightIndex = index;
}
}
return (new int[] {leftIndex, rightIndex});
}
}
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] sortedNums = Arrays.copyOf(nums, nums.length);
Arrays.sort(sortedNums);
int leftSortedIndex = 0;
int rightSortedIndex = sortedNums.length - 1;
while(leftSortedIndex < rightSortedIndex) {
int sum = sortedNums[leftSortedIndex] + sortedNums[rightSortedIndex];
if(sum == target) {
break;
} else if(sum < target) {
leftSortedIndex++;
} else {
rightSortedIndex--;
}
}
int leftIndex = -1;
int rightIndex = -1;
for(int index=0; index < nums.length; index++) {
if(leftIndex == -1 && nums[index] == sortedNums[leftSortedIndex]) {
leftIndex = index;
} else if(rightIndex == -1 && nums[index] == sortedNums[rightSortedIndex]) {
rightIndex = index;
}
}
return (new int[] {leftIndex, rightIndex});
}
}
If anyone want for C this might help...It is brute forced not with hashtable!
#include <stdio.h>
int main(int argc, char const *argv[])
{
int i,j,l,target,m,n;
printf("Enter how many elements you want :\n");
scanf("%d",&i);
int array[i];
printf("Input elements\n" );
for (j=0;j<i;j++)
scanf("%d",&array[j]);
printf("[");
for (l=0;l<i;l++)
printf(" %d ",array[l] );
printf("]\n");
printf("Input the target :");
scanf("%d",&target);
for (m=0;m<i;m++)
{
for (n=m+1;n<i;n++)
{
if ((array[m]+array[n])==target)
{
printf("Their indices is \n[%d,%d]",m,n);
}
}
}
return 0;
}