How to sort an array in a single loop? - algorithm
So I was going through different sorting algorithms. But almost all the sorting algorithms require 2 loops to sort the array. The time complexity of Bubble sort & Insertion sort is O(n) for Best case but is O(n^2) as worst case which again requires 2 loops. Is there a way to sort an array in a single loop?
Here, a single-loop Bubble Sort in Python:
def bubbly_sortish(data):
for _ in xrange(len(data)**2):
i, j = _/len(data), _%len(data)
if i<j and data[i] > data[j]:
data[i], data[j] = data[j], data[i]
A = [5, 1, 2, 3, 5, 6, 10]
bubbly_sortish(A)
print A
Of course this is a joke. But this shows the number of loops has little to do with algorithm complexity.
Now, if you're asking if it is possible to sort an array with O(n) comparisons, no, it's not possible. The lower bound is Ω(n log n) for comparison-based sorting algorithms.
int list[] = { 45, 78, 22, 96, 10, 87, 68, 2 };
for (int i = 1; i < list.length; i++) {
if (list[i] < list[i - 1]) {
list[i] = list[i] + list[i - 1];
list[i - 1] = list[i] - list[i - 1];
list[i] = list[i] - list[i - 1];
i = 0;
}
}
System.out.print("Sorted array is : ");
for (int i = 0; i < list.length; i++) {
System.out.print(list[i] + " ");
}
Single Loop Bubble Sort using C++
int a[7]={5,7,6,2,4,3,1};
int temp = 0;
int j = 0;
for(int i = 0 ; i<a[]-1 ; i++)
{
int flag = 0;
if(a[i]>a[i+1])
{
temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
flag = 1;
}
if(i == 7-2-j)
{
if(!flag) break;
i = -1;
j++;
}
}
In the general case you have O(n lg n) as an average.
But in particular cases, the best case is O(n), which I consider close enough to what you'd call "only one loop", even though the implementation may show more than one instance of the for keyword. And the good news with that, is that you're not depending on luck to make your best case a reality. Provided you know a few properties about your data, you can pick some specific algorithms. For example :
3-way quicksort runs very near O(n) when you have a lot of items with only a few distinct sorting keys (think server log entries as items and dates as keys).
Counting sort runs in O(n+k) if your keys are easily indexable (like a character set, or small integers), and the index has a known upper bound k.
Burstsort will run in O(wn) if you're dealing with strings of maximum length w.
Those are but three examples. There are many more, way too many to recall from the top of my head, for many types of constrained data sets.
If you have a real-life case at hand where O(n lg n) is not good enough, it's well worth doing some proper research, provided you identified a few interesting properties in your data.
javascript:
function bruteForce(arr){
for(var i=0;i<arr.length; ){
if(arr[i+1]< arr[i]){
var temp = arr[i];
arr[i]=arr[i+1];
arr[i+1] = temp;
i--;
if(i === -1) i=0;
}else i++;
}
return arr;
}
alert(bruteForce([2,3,4,5,6,23,1,1]));
Copy the code and paste in URL of the browser and hit enter. If the javascript: is missed then add it.
Here is the code to sort array using only single loop.
var array = [100, 110, 111, 1, 3, 19, 1, 11, -10]
var i = 1
while i < array.count - 1 {
if array[i] > array[i + 1] {
let temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
i = -1;
}
i = i + 1;
}
print(array)
Here is a working version for your given example:
One very fast efficiant and logical way of doing the problem works if you know the range of the values to be sorted, for example
0 <= val <= 100 where val is integer.
Then you can do it with a single read and write operation in only two loops... one for reading the array, one for writing it sorted:
Use a second array where the indices represent values 0-100, store in it the number of times every value 0-100 is encountered, for example val = 100 could exist 234 times in your target array...
There is only one loop for reading and one loop for writing, which is computationally as efficient as one loop which would do both the reading and the writing and faster than a loop that uses comparison... If you insist, you can do it in a single loop twice as long as the target array's length and reset i value to zero on the new array write operation.
The second loop simply writes in order the count of every value encountered in the first array.
Single loop array sort:
for(int i = 0, j=i+1; i < arr.length && j<arr.length;)
{
if(arr[i] > arr[j])
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i=0;
j=i+1;
}
else
{
i++;
j++;
}
}
public void sortArrayUsingSingleLoop(int[] intArray) {
int temp;
boolean swap = false;
for(int i=0;i<intArray.length-1;i++){
if(intArray[i]>intArray[i+1]){
temp=intArray[i];
intArray[i]=intArray[i+1];
intArray[i+1]=temp;
swap=true;
}
if(swap &&i==intArray.length-2){
i=-1;swap=false;
}
}
}
The following code is in php. you can test the code on https://paiza.io/projects/4pAp6CuB-e9vhGIblDNCZQ.
$a = [8,3,4,9,1];
for($i=0;$i<count($a)-1;$i++){
if($a[$i] > $a[$i+1]){
$temp = $a[$i];
$a[$i] = $a[$i+1];
$a[$i+1] = $temp;
$i = -1;
}
}
print_r($a);
public class SinleLoopeSorting {
public static void main(String[] args) {
Integer[] x = new Integer[] { 1, 7, 8, 0, 4, 2, 3 };
for (int i = 0; i < x.length - 1; i++) {
if (x[i] > x[i + 1]) {
int p = x[i];
x[i] = x[i + 1];
x[i + 1] = p;
i = -1;
}
}
for (int i = 0; i < x.length; i++) {
System.out.println(x[i]);
}
}
}
This can be used to sort array usinga single loop:-
Points to be noed:
updating the value of i to -1 so that it alwasy starts from 0 after i++
reducing the length(size--) of array as maximum valued element ends up at the end for every time the loop completes
Code:
void sort(int *arr,int size){
int i;
for (i = 0; i <size; i++){
if(arr[i]>arr[i+1]){
arr[i]=arr[i]+arr[i+1];
arr[i+1]=arr[i]-arr[i+1];
arr[i]=arr[i]-arr[i+1];
if(i==size-2){
printf("%s\n","inside if loop" );
i=-1;
size--;
}
}
}
}
def my_sort(num_list):
x = 0
while x < len(num_list) - 1:
if num_list[x] > num_list[x+1]:
num_list[x], num_list[x+1] = num_list[x+1], num_list[x]
x = -1
x += 1
return num_list
print(my_sort(num_list=[14, 46, 43, 27, 57, 42, 45, 21, 70]))
#output [14, 21, 27, 42, 43, 45, 46, 57, 70]
Single for loop for insertion sort:
strong text
function insertionSort (array) {
for(var i = 1 ; i < array.length ;){
if(array[1] < array[0]) {
temp = array[i];
array[i] = array[i -1];
array[i -1] = temp;
}
if(array[i] < array[i-1]){
var temp = array[i]
array[i] = array[i -1]
array[i -1] = temp
i--
} else{i++}
}
return array
}
Sorting an array using single loop (javascript)
var arr = [4,5,2,10,3,7,11,5,1];
for(var i = 1; i < arr.length; i++)
{
if(arr[i] < arr[i-1])
{
arr[i] = arr[i] + arr[i-1];
arr[i-1] = arr[i] - arr[i-1];
arr[i] = arr[i] - arr[i-1];
i=0;
}
}
output : arr = [1, 2, 3, 4, 5, 5, 7, 10, 11]
The following code is in PHP to sort an array best case possible.
https://paiza.io/projects/r22X0VuHvPQ236jgkataxg
<?php
function quicksort($a){
$n = count($a);
$lt = [];
$gt = [];
if($n < 2){
return $a;
}else{
$f = $a[0];
}
for($i = 1;$i < $n ;$i++){
if($a[$i] > $f){
$gt [] = $a[$i];
}else{
$lt [] = $a[$i];
}
}
return array_merge(quicksort($lt),array($f),quicksort($gt));
}
$ar = [7,4,3,6,5,1,2];
echo "Input array => ".implode(' , ',$ar).'<br>';
$a = quicksort($ar);
echo "Output array => ".implode(' , ',$a);;
?>
Sorting an array using java in Single Loop:
public int[] getSortedArrayInOneLoop(int[] arr) {
int temp;
int j;
for (int i = 1; i < arr.length; i++) {
j = i - 1;
if (arr[i] < arr[j]) {
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
i = 1;
}
}
return arr;
}
Late to the party but hope this helps
java solution
for(int i=1;i< arr.length;i++) {
if(arr[i] < arr[i-1] ){
arr[i-1] += arr[i];
arr[i] = arr[i-1] - arr[i];
arr[i-1] -= arr[i];
i=0;
}
}
with python:
def sort(array):
n = len(array);
i = 0;
mod = 0;
if(len(array)<= 1):
return(array)
while n-1:
if array[mod] > array[mod+1]:
array[mod], array[mod+1] = array[mod+1], array[mod]
mod+=1
if mod+1 >= n:
n-=1
mod = 0
return array
#include<stdio.h>
void sort(int a[],int n,int k,int w)
{
int i,j,z,key;
n=n-1;
j = k+1;
key = a[j];
i = j-1;
while(i>0 && a[i]>key)
{
a[i+1] = a[i];
i = i-1;
}
a[i+1] = key;
k = k + 1;
if(n!=0)
{
sort(a,n,k,w);
}
}
int main()
{
int i,n,w,k=1,z=5,g;
printf("enter the size of an array\n");
scanf("%d",&n);
g=n;
int a[n];
for(i=1;i<=n;i++)
{
scanf("%d", &a[i]);
}
w = n;
sort(a,n-1,k,w);
for(i = 1; i <= n; i++)
{
printf("%d", a[i]);
}
}
Here is the solution. This might help you.
public int find2ndLargest() {
int[] arr = {1,3,14,25,7,20,11,30};
int temp;
// sort array
for (int i=0;i<arr.length-1;i++) {
if (arr[i]>arr[i+1]) {
temp = arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
i=0;
}
}
return arr[arr.length-2];
}
static int[] sort(int[] arr){
int idx = 0;
int len = arr.length - 1;
int counter = len;
while(true){
if(idx != len && arr[idx] > arr[idx+1]){
swap(arr, idx, idx + 1);
counter--;
}
idx++;
if(counter == len && idx == len){
break;
}
if(idx == len){
idx = 0;
counter = len;
}
}
return arr;
}
void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
it as much simple as below, please flow easy step
var arr=[5,1,4,3];
for(var i=0;i<arr.length-1;i++){
var num=arr[i];
var num2=arr[i+1];
//Check if first index value with next index value
if(num>num2){
var temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
//assign i=0 to re start the loop to check the index value
i=0;
}
}
console.log(arr)
you can use a while loop and play around with the index
int i=0;
int a[]={1,2,3,4,7,3};
while(i<a.length)
{
if((i+1<a.length && a[i]>a[i+1]) )
{
swap(i,i+1,a);
i=i-1;
}
if(i-1>=0 && a[i]<a[i-1] )
{
swap(i,i-1,a);
i=i-1;
}
else
i++;
}
Related
Maximum sum Sequence such that no two elements are adjacent
My implementation of max sum is below but i need sequence which is giving max sum i looked on google and stackoverflow but nowhere sequence is output. public int maxSum(int arr[]) { int excl = 0; int incl = arr[0]; for (int i = 1; i < arr.length; i++) { int temp = incl; incl = Math.max(excl + arr[i], incl); excl = temp; } return incl; } So 3 2 7 10 should return (3 and 10) or 3 2 5 10 7 should return (3, 5 and 7) or {5, 5, 10, 100, 10, 5} will return (5, 100 and 5) or {1, 20, 3} will return 20 i exactly want this problem solution but return value i need is sequence of elements included in max sum instead of max sum value
You mean that in this array: [1,3,4,2,4,7,5,3] , calculate [1+4+4+5] and [3+2+7+3] and return the bigger one? If you do so, this is my algorithm: public int maxSum(int arr[]) { int sum1 = 0; int sum2 = 0; for(int i = 0; i < arr.length; i+=2) sum1 += arr[i]; for(int i = 1; i < arr.length; i+=2) sum2 += arr[i]; return Math.max(sum1, sum2); } Or this one: public int maxSum(int arr[]) { int sum1 = 0; int sum2 = 0; for(int i = 0; i < arr.length; i+=2) sum1 += arr[i]; try {sum2 += arr[i + 1];} catch(ArrayIndexOutOfBoundsException e){} } return Math.max(sum1, sum2); }
Looks similar to Longest Increasing Fragment problem(Top Down approach.) Instead of having length of sequence, you can return sum of it. Also, instead of skipping one, skipping two to avoid adjacent elements.
#simplest and clean solution public int maxSubsetSumNoAdjacent(int[] arr) { if(arr.length == 0){ return 0; } if(arr.length == 1){ return arr[0]; } int a =arr[0]; int b= 0; int c =a; int i=1; while(i<arr.length){ a=arr[i]+b; b=Math.max(c,b); c=a; i++; } return Math.max(a,b); }
Find zeroes to be flipped so that number of consecutive 1’s is maximized
Find zeroes to be flipped so that number of consecutive 1’s is maximized. Input: arr[] = {1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1} m = 2 Output: 5 7 We are allowed to flip maximum 2 zeroes. If we flip arr[5] and arr[7], we get 8 consecutive 1's which is maximum possible under given constraints . Now if we were to find just the maximum number of 1's that is possible, is it possible to solve using dynamic programming approach?
This problem can be solved in linear time O(N) and linear space O(N). Its not full fledged dynamic programming, but its similar to that as it uses precomputation. Data Structures Used: 1.left: It is an integer array, of same length as given array. It is precomputed such that for every position i: left[i] = Number of consecutive 1's to the left position i 2.right: It is an integer array, of same length as given array. It is precomputed such that for every position i: right[i] = Number of consecutive 1's to the right position i These can be computed in single traversal of the array.Assuming arr is the original array, following pseudocode does the job: Pseudocode for populating left array left() { int count = 0; for(int i = 0;i < arr length; ++i) { if(i == 0) { left[i] = 0; if(arr[i] == 1) count++; continue; } else { left[i] = count; if(arr[i] == 1) count++; else count = 0; } } } Pseudocode for populating right array right() { int count = 0; for(int i = arr length - 1;i >= 0; --i) { if(i == arr length - 1) { right[i] = 0; if(arr[i] == 1) count++; continue; } else { right[i] = count; if(arr[i] == 1) count++; else count = 0; } } } Now the only thing we have to do is :check all pair of positions i and j (i < j) such that arr[i] = 0 and arr[j] = 0 and for no position between i and j arr[i] should be 0 and Keep track of the pair for which we get maximum value of the following: left[i] + right[j] + right[l] You could also use left[i] + right[j] + left[r]. left[i] tells the number of consecutive 1's to the left of position i and right[j] tells the number of consecutive 1's to the right of position j and the number of consecutive 1's between i and j can be counted be left[r] OR right[l], and therefore, we have two candidate expressions. This can also be done in single traversal, using following pseudocode: max_One() { max = 0; l = -1, r = -1; for(int i = 0;i < arr length; ++i) { if(arr[i] == 0) { if(l == -1) l = i; else { r = i; if(left[l] + right[r] + right[l] > max) { max = left[l] + right[r] + right[l]; left_pos = l; right_pos = r; } l = r; } } } }
You should use sliding window concept here - use start and end vars to store index of range. Whenever you encounter a 0, increment the counter of zeros received. Include it in current length.. If zeros encounter equals m+1, increment start till you encounter 0. public static int[] zerosToFlip(int[] input, int m) { if (m == 0) return new int[0]; int[] indices = new int[m]; int beginIndex = 0; int endIndex = 0; int maxBeginIndex=0; int maxEndIndex=0; int zerosIncluded = input[0] == 0 ? 1 : 0; for (int i = 1; i < input.length; i++) { if (input[i] == 0) { if (zerosIncluded == m) { if (endIndex - beginIndex > maxEndIndex - maxBeginIndex){ maxBeginIndex = beginIndex; maxEndIndex = endIndex; } while (input[beginIndex] != 0) beginIndex++; beginIndex++; } else { zerosIncluded++; } } endIndex++; } if (endIndex - beginIndex > maxEndIndex - maxBeginIndex){ maxBeginIndex = beginIndex; maxEndIndex = endIndex; } int j = 0; for (int i = maxBeginIndex; i <= maxEndIndex; i++) { if (input[i] == 0) { indices[j] = i; ++j; } } return indices; }
Type of sorting algorithm
What type of sorting algorithm is this: private static void Sort(int[] array) { int a=0,b=0; for (int j = 1; j < array.length; j++) { int index = array[j]; int previouse_index = j-1; while ( (previouse_index >= 0 ) && ( array [previouse_index] < index ) ) { array [previouse_index + 1] = array [previouse_index]; previouse_index--; b++; } array[previouse_index+1] = index; printNumbers(array); a++; } System.out.println("for loop iteration "+ a); System.out.println("while loop iteration "+ b); } Is it bubble sort? or insertion sort? or something completely different?
After eliminating useless code, renaming variables and formatting it: private static void Sort(int[] array) { for (int j = 1; j < array.length; j++) { int value = array[j]; int index = j-1; while ( (index >= 0) && (array[index] < value) ) { array[index + 1] = array[index]; index--; } array[index + 1] = value; } } Now it is easy to see, that in the inner while-loop big values rise up in the array (like bubbles in the water), hence it's indeed an implementation of the Bubble Sort Algorithm
Bubble Sort using Bubble Up
Given the algorithm for Bubble Sort: Algorithm BubbleSort(A[0...n]): for i <- 0 to n-2 do for j <- 0 to n-2-i do if(A[j+1] < A[j] then swap(A[j], A[j+1])) I have to rewrite the Bubble Sort algorithm using where we "Bubble Up" the smallest element to the ith position on the ith pass through the list. Can anyone help me with this?
Currently you are traversing the array from the start, therefore if you come upon the largest element, it will be "Bubbled up" to the end of the array. If you want to do the opposite, "Bubbling down" the smallest element to the start, you need to traverse the array in the opposite direction, from the end to the start. Hope it helps you to find the way.
#include<stdio.h> void bubbleSort(int *x,int size) { int e,f,m,g; m=size-2; while(m>0) { e=0; f=1; while(e<=m) { if(x[f]<x[e]) { g=x[e]; //swaping x[e]=x[f]; x[f]=g; } e++; f++; } m--; } } void main() { int x[10],y; for(y=0;y<=9;y++) //loop to insert 10 numbers into an array { printf("Enter a number: "); scanf("%d",&x[y]); } bubbleSort(x,10); //pass number entered by user and size of array to bubbleSort for(y=0;y<=9;y++) //loop to print sorted numbers { printf("%d\n",x[y]); } }
Looks like the answer to this has not been accepted yet. Hence trying to check if this is still an issue. Here is what I think can be a possible implementation in Java. As #Warlord mentioned, the algorithm is to ensure that the array in concern for sorting is imagined as a vertical array. With each pass, all we are doing is check if there is a larger element below and if found that element is bubbled up to the top. static void bubbleUpSort(int[] arr){ final int N = arr.length; int tmp = 0; for (int i=0; i < N; i++){ for (int j=N-1; j >= i+1; j--){ if (arr[j] < arr[j-1]){ tmp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = tmp; } } } for (int k =0; k < arr.length; k++){ System.out.print(arr[k] + " "); } } Called from main as: public static void main(String[] args) { System.out.println("Bubble Up Sort"); int[] bUp = {19, 2, 9, 4, 7, 12, 13, 3, 6}; bubbleUpSort(bUp); }
Bubble Sort Comparing each with the neighbor and swapping if first is greater than the next function bubbleSort(arr){ let temp; console.log("Input Array"); console.log(arr); for (let i = 0; i < arr.length-1; i++) { for (let j = 0; j < arr.length-i-1; j++) { if (arr[j] > arr[j+1]) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; console.log(arr[j],"swapped with",arr[j+1]) console.log(arr); } else { console.log("SKIP"); } } } console.log("Sorted using Bubble Sort"); return arr; } console.log(bubbleSort([7,6,9,8,2,1,4,3,5]));
Find a pair of elements from an array whose sum equals a given number
Given array of n integers and given a number X, find all the unique pairs of elements (a,b), whose summation is equal to X. The following is my solution, it is O(nLog(n)+n), but I am not sure whether or not it is optimal. int main(void) { int arr [10] = {1,2,3,4,5,6,7,8,9,0}; findpair(arr, 10, 7); } void findpair(int arr[], int len, int sum) { std::sort(arr, arr+len); int i = 0; int j = len -1; while( i < j){ while((arr[i] + arr[j]) <= sum && i < j) { if((arr[i] + arr[j]) == sum) cout << "(" << arr[i] << "," << arr[j] << ")" << endl; i++; } j--; while((arr[i] + arr[j]) >= sum && i < j) { if((arr[i] + arr[j]) == sum) cout << "(" << arr[i] << "," << arr[j] << ")" << endl; j--; } } }
There are 3 approaches to this solution: Let the sum be T and n be the size of array Approach 1: The naive way to do this would be to check all combinations (n choose 2). This exhaustive search is O(n2). Approach 2: A better way would be to sort the array. This takes O(n log n) Then for each x in array A, use binary search to look for T-x. This will take O(nlogn). So, overall search is O(n log n) Approach 3 : The best way would be to insert every element into a hash table (without sorting). This takes O(n) as constant time insertion. Then for every x, we can just look up its complement, T-x, which is O(1). Overall the run time of this approach is O(n). You can refer more here.Thanks.
# Let arr be the given array. # And K be the give sum for i=0 to arr.length - 1 do # key is the element and value is its index. hash(arr[i]) = i end-for for i=0 to arr.length - 1 do # if K-th element exists and it's different then we found a pair if hash(K - arr[i]) != i print "pair i , hash(K - arr[i]) has sum K" end-if end-for
Implementation in Java : Using codaddict's algorithm (Maybe slightly different) import java.util.HashMap; public class ArrayPairSum { public static void main(String[] args) { int []a = {2,45,7,3,5,1,8,9}; printSumPairs(a,10); } public static void printSumPairs(int []input, int k){ Map<Integer, Integer> pairs = new HashMap<Integer, Integer>(); for(int i=0;i<input.length;i++){ if(pairs.containsKey(input[i])) System.out.println(input[i] +", "+ pairs.get(input[i])); else pairs.put(k-input[i], input[i]); } } } For input = {2,45,7,3,5,1,8,9} and if Sum is 10 Output pairs: 3,7 8,2 9,1 Some notes about the solution : We iterate only once through the array --> O(n) time Insertion and lookup time in Hash is O(1). Overall time is O(n), although it uses extra space in terms of hash.
Solution in java. You can add all the String elements to an ArrayList of strings and return the list. Here I am just printing it out. void numberPairsForSum(int[] array, int sum) { HashSet<Integer> set = new HashSet<Integer>(); for (int num : array) { if (set.contains(sum - num)) { String s = num + ", " + (sum - num) + " add up to " + sum; System.out.println(s); } set.add(num); } }
Python Implementation: import itertools list = [1, 1, 2, 3, 4, 5,] uniquelist = set(list) targetsum = 5 for n in itertools.combinations(uniquelist, 2): if n[0] + n[1] == targetsum: print str(n[0]) + " + " + str(n[1]) Output: 1 + 4 2 + 3
C++11, run time complexity O(n): #include <vector> #include <unordered_map> #include <utility> std::vector<std::pair<int, int>> FindPairsForSum( const std::vector<int>& data, const int& sum) { std::unordered_map<int, size_t> umap; std::vector<std::pair<int, int>> result; for (size_t i = 0; i < data.size(); ++i) { if (0 < umap.count(sum - data[i])) { size_t j = umap[sum - data[i]]; result.push_back({data[i], data[j]}); } else { umap[data[i]] = i; } } return result; }
Here is a solution witch takes into account duplicate entries. It is written in javascript and assumes array is sorted. The solution runs in O(n) time and does not use any extra memory aside from variable. var count_pairs = function(_arr,x) { if(!x) x = 0; var pairs = 0; var i = 0; var k = _arr.length-1; if((k+1)<2) return pairs; var halfX = x/2; while(i<k) { var curK = _arr[k]; var curI = _arr[i]; var pairsThisLoop = 0; if(curK+curI==x) { // if midpoint and equal find combinations if(curK==curI) { var comb = 1; while(--k>=i) pairs+=(comb++); break; } // count pair and k duplicates pairsThisLoop++; while(_arr[--k]==curK) pairsThisLoop++; // add k side pairs to running total for every i side pair found pairs+=pairsThisLoop; while(_arr[++i]==curI) pairs+=pairsThisLoop; } else { // if we are at a mid point if(curK==curI) break; var distK = Math.abs(halfX-curK); var distI = Math.abs(halfX-curI); if(distI > distK) while(_arr[++i]==curI); else while(_arr[--k]==curK); } } return pairs; } I solved this during an interview for a large corporation. They took it but not me. So here it is for everyone. Start at both side of the array and slowly work your way inwards making sure to count duplicates if they exist. It only counts pairs but can be reworked to find the pairs find pairs < x find pairs > x Enjoy!
O(n) def find_pairs(L,sum): s = set(L) edgeCase = sum/2 if L.count(edgeCase) ==2: print edgeCase, edgeCase s.remove(edgeCase) for i in s: diff = sum-i if diff in s: print i, diff L = [2,45,7,3,5,1,8,9] sum = 10 find_pairs(L,sum) Methodology: a + b = c, so instead of looking for (a,b) we look for a = c - b
Implementation in Java : Using codaddict's algorithm: import java.util.Hashtable; public class Range { public static void main(String[] args) { // TODO Auto-generated method stub Hashtable mapping = new Hashtable(); int a[]= {80,79,82,81,84,83,85}; int k = 160; for (int i=0; i < a.length; i++){ mapping.put(a[i], i); } for (int i=0; i < a.length; i++){ if (mapping.containsKey(k - a[i]) && (Integer)mapping.get(k-a[i]) != i){ System.out.println(k-a[i]+", "+ a[i]); } } } } Output: 81, 79 79, 81 If you want duplicate pairs (eg: 80,80) also then just remove && (Integer)mapping.get(k-a[i]) != i from the if condition and you are good to go.
Just attended this question on HackerRank and here's my 'Objective C' Solution: -(NSNumber*)sum:(NSArray*) a andK:(NSNumber*)k { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; long long count = 0; for(long i=0;i<a.count;i++){ if(dict[a[i]]) { count++; NSLog(#"a[i]: %#, dict[array[i]]: %#", a[i], dict[a[i]]); } else{ NSNumber *calcNum = #(k.longLongValue-((NSNumber*)a[i]).longLongValue); dict[calcNum] = a[i]; } } return #(count); } Hope it helps someone.
this is the implementation of O(n*lg n) using binary search implementation inside a loop. #include <iostream> using namespace std; bool *inMemory; int pairSum(int arr[], int n, int k) { int count = 0; if(n==0) return count; for (int i = 0; i < n; ++i) { int start = 0; int end = n-1; while(start <= end) { int mid = start + (end-start)/2; if(i == mid) break; else if((arr[i] + arr[mid]) == k && !inMemory[i] && !inMemory[mid]) { count++; inMemory[i] = true; inMemory[mid] = true; } else if(arr[i] + arr[mid] >= k) { end = mid-1; } else start = mid+1; } } return count; } int main() { int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; inMemory = new bool[10]; for (int i = 0; i < 10; ++i) { inMemory[i] = false; } cout << pairSum(arr, 10, 11) << endl; return 0; }
In python arr = [1, 2, 4, 6, 10] diff_hash = {} expected_sum = 3 for i in arr: if diff_hash.has_key(i): print i, diff_hash[i] key = expected_sum - i diff_hash[key] = i
Nice solution from Codeaddict. I took the liberty of implementing a version of it in Ruby: def find_sum(arr,sum) result ={} h = Hash[arr.map {|i| [i,i]}] arr.each { |l| result[l] = sum-l if h[sum-l] && !result[sum-l] } result end To allow duplicate pairs (1,5), (5,1) we just have to remove the && !result[sum-l] instruction
Here is Java code for three approaches: 1. Using Map O(n), HashSet can also be used here. 2. Sort array and then use BinarySearch to look for complement O(nLog(n)) 3. Traditional BruteForce two loops O(n^2) public class PairsEqualToSum { public static void main(String[] args) { int a[] = {1,10,5,8,2,12,6,4}; findPairs1(a,10); findPairs2(a,10); findPairs3(a,10); } //Method1 - O(N) use a Map to insert values as keys & check for number's complement in map static void findPairs1(int[]a, int sum){ Map<Integer, Integer> pairs = new HashMap<Integer, Integer>(); for(int i=0; i<a.length; i++){ if(pairs.containsKey(sum-a[i])) System.out.println("("+a[i]+","+(sum-a[i])+")"); else pairs.put(a[i], 0); } } //Method2 - O(nlog(n)) using Sort static void findPairs2(int[]a, int sum){ Arrays.sort(a); for(int i=0; i<a.length/2; i++){ int complement = sum - a[i]; int foundAtIndex = Arrays.binarySearch(a,complement); if(foundAtIndex >0 && foundAtIndex != i) //to avoid situation where binarySearch would find the original and not the complement like "5" System.out.println("("+a[i]+","+(sum-a[i])+")"); } } //Method 3 - Brute Force O(n^2) static void findPairs3(int[]a, int sum){ for(int i=0; i<a.length; i++){ for(int j=i; j<a.length;j++){ if(a[i]+a[j] == sum) System.out.println("("+a[i]+","+a[j]+")"); } } } }
A Simple program in java for arrays having unique elements: import java.util.*; public class ArrayPairSum { public static void main(String[] args) { int []a = {2,4,7,3,5,1,8,9,5}; sumPairs(a,10); } public static void sumPairs(int []input, int k){ Set<Integer> set = new HashSet<Integer>(); for(int i=0;i<input.length;i++){ if(set.contains(input[i])) System.out.println(input[i] +", "+(k-input[i])); else set.add(k-input[i]); } } }
A simple Java code snippet for printing the pairs below: public static void count_all_pairs_with_given_sum(int arr[], int S){ if(arr.length < 2){ return; } HashSet values = new HashSet(arr.length); for(int value : arr)values.add(value); for(int value : arr){ int difference = S - value; if(values.contains(difference) && value<difference){ System.out.printf("(%d, %d) %n", value, difference); } } }
Another solution in Swift: the idea is to create an hash that store values of (sum - currentValue) and compare this to the current value of the loop. The complexity is O(n). func findPair(list: [Int], _ sum: Int) -> [(Int, Int)]? { var hash = Set<Int>() //save list of value of sum - item. var dictCount = [Int: Int]() //to avoid the case A*2 = sum where we have only one A in the array var foundKeys = Set<Int>() //to avoid duplicated pair in the result. var result = [(Int, Int)]() //this is for the result. for item in list { //keep track of count of each element to avoid problem: [2, 3, 5], 10 -> result = (5,5) if (!dictCount.keys.contains(item)) { dictCount[item] = 1 } else { dictCount[item] = dictCount[item]! + 1 } //if my hash does not contain the (sum - item) value -> insert to hash. if !hash.contains(sum-item) { hash.insert(sum-item) } //check if current item is the same as another hash value or not, if yes, return the tuple. if hash.contains(item) && (dictCount[item] > 1 || sum != item*2) // check if we have item*2 = sum or not. { if !foundKeys.contains(item) && !foundKeys.contains(sum-item) { foundKeys.insert(item) //add to found items in order to not to add duplicated pair. result.append((item, sum-item)) } } } return result } //test: let a = findPair([2,3,5,4,1,7,6,8,9,5,3,3,3,3,3,3,3,3,3], 14) //will return (8,6) and (9,5)
My Solution - Java - Without duplicates public static void printAllPairSum(int[] a, int x){ System.out.printf("printAllPairSum(%s,%d)\n", Arrays.toString(a),x); if(a==null||a.length==0){ return; } int length = a.length; Map<Integer,Integer> reverseMapOfArray = new HashMap<>(length,1.0f); for (int i = 0; i < length; i++) { reverseMapOfArray.put(a[i], i); } for (int i = 0; i < length; i++) { Integer j = reverseMapOfArray.get(x - a[i]); if(j!=null && i<j){ System.out.printf("a[%d] + a[%d] = %d + %d = %d\n",i,j,a[i],a[j],x); } } System.out.println("------------------------------"); }
This prints the pairs and avoids duplicates using bitwise manipulation. public static void findSumHashMap(int[] arr, int key) { Map<Integer, Integer> valMap = new HashMap<Integer, Integer>(); for(int i=0;i<arr.length;i++) valMap.put(arr[i], i); int indicesVisited = 0; for(int i=0;i<arr.length;i++) { if(valMap.containsKey(key - arr[i]) && valMap.get(key - arr[i]) != i) { if(!((indicesVisited & ((1<<i) | (1<<valMap.get(key - arr[i])))) > 0)) { int diff = key-arr[i]; System.out.println(arr[i] + " " +diff); indicesVisited = indicesVisited | (1<<i) | (1<<valMap.get(key - arr[i])); } } } }
I bypassed the bit manuplation and just compared the index values. This is less than the loop iteration value (i in this case). This will not print the duplicate pairs and duplicate array elements also. public static void findSumHashMap(int[] arr, int key) { Map<Integer, Integer> valMap = new HashMap<Integer, Integer>(); for (int i = 0; i < arr.length; i++) { valMap.put(arr[i], i); } for (int i = 0; i < arr.length; i++) { if (valMap.containsKey(key - arr[i]) && valMap.get(key - arr[i]) != i) { if (valMap.get(key - arr[i]) < i) { int diff = key - arr[i]; System.out.println(arr[i] + " " + diff); } } } }
in C#: int[] array = new int[] { 1, 5, 7, 2, 9, 8, 4, 3, 6 }; // given array int sum = 10; // given sum for (int i = 0; i <= array.Count() - 1; i++) if (array.Contains(sum - array[i])) Console.WriteLine("{0}, {1}", array[i], sum - array[i]);
One Solution can be this, but not optimul (The complexity of this code is O(n^2)): public class FindPairsEqualToSum { private static int inputSum = 0; public static List<String> findPairsForSum(int[] inputArray, int sum) { List<String> list = new ArrayList<String>(); List<Integer> inputList = new ArrayList<Integer>(); for (int i : inputArray) { inputList.add(i); } for (int i : inputArray) { int tempInt = sum - i; if (inputList.contains(tempInt)) { String pair = String.valueOf(i + ", " + tempInt); list.add(pair); } } return list; } }
A simple python version of the code that find a pair sum of zero and can be modify to find k: def sumToK(lst): k = 0 # <- define the k here d = {} # build a dictionary # build the hashmap key = val of lst, value = i for index, val in enumerate(lst): d[val] = index # find the key; if a key is in the dict, and not the same index as the current key for i, val in enumerate(lst): if (k-val) in d and d[k-val] != i: return True return False The run time complexity of the function is O(n) and Space: O(n) as well.
public static int[] f (final int[] nums, int target) { int[] r = new int[2]; r[0] = -1; r[1] = -1; int[] vIndex = new int[0Xfff]; for (int i = 0; i < nums.length; i++) { int delta = 0Xff; int gapIndex = target - nums[i] + delta; if (vIndex[gapIndex] != 0) { r[0] = vIndex[gapIndex]; r[1] = i + 1; return r; } else { vIndex[nums[i] + delta] = i + 1; } } return r; }
less than o(n) solution will be=> function(array,k) var map = {}; for element in array map(element) = true; if(map(k-element)) return {k,element}
Solution in Python using list comprehension f= [[i,j] for i in list for j in list if j+i==X]; O(N2) also gives two ordered pairs- (a,b) and (b,a) as well
I can do it in O(n). Let me know when you want the answer. Note it involves simply traversing the array once with no sorting, etc... I should mention too that it exploits commutativity of addition and doesn't use hashes but wastes memory. using System; using System.Collections.Generic; /* An O(n) approach exists by using a lookup table. The approach is to store the value in a "bin" that can easily be looked up(e.g., O(1)) if it is a candidate for an appropriate sum. e.g., for each a[k] in the array we simply put the it in another array at the location x - a[k]. Suppose we have [0, 1, 5, 3, 6, 9, 8, 7] and x = 9 We create a new array, indexes value 9 - 0 = 9 0 9 - 1 = 8 1 9 - 5 = 4 5 9 - 3 = 6 3 9 - 6 = 3 6 9 - 9 = 0 9 9 - 8 = 1 8 9 - 7 = 2 7 THEN the only values that matter are the ones who have an index into the new table. So, say when we reach 9 or equal we see if our new array has the index 9 - 9 = 0. Since it does we know that all the values it contains will add to 9. (note in this cause it's obvious there is only 1 possible one but it might have multiple index values in it which we need to store). So effectively what we end up doing is only having to move through the array once. Because addition is commutative we will end up with all the possible results. For example, when we get to 6 we get the index into our new table as 9 - 6 = 3. Since the table contains that index value we know the values. This is essentially trading off speed for memory. */ namespace sum { class Program { static void Main(string[] args) { int num = 25; int X = 10; var arr = new List<int>(); for(int i = 0; i <= num; i++) arr.Add((new Random((int)(DateTime.Now.Ticks + i*num))).Next(0, num*2)); Console.Write("["); for (int i = 0; i < num - 1; i++) Console.Write(arr[i] + ", "); Console.WriteLine(arr[arr.Count-1] + "] - " + X); var arrbrute = new List<Tuple<int,int>>(); var arrfast = new List<Tuple<int,int>>(); for(int i = 0; i < num; i++) for(int j = i+1; j < num; j++) if (arr[i] + arr[j] == X) arrbrute.Add(new Tuple<int, int>(arr[i], arr[j])); int M = 500; var lookup = new List<List<int>>(); for(int i = 0; i < 1000; i++) lookup.Add(new List<int>()); for(int i = 0; i < num; i++) { // Check and see if we have any "matches" if (lookup[M + X - arr[i]].Count != 0) { foreach(var j in lookup[M + X - arr[i]]) arrfast.Add(new Tuple<int, int>(arr[i], arr[j])); } lookup[M + arr[i]].Add(i); } for(int i = 0; i < arrbrute.Count; i++) Console.WriteLine(arrbrute[i].Item1 + " + " + arrbrute[i].Item2 + " = " + X); Console.WriteLine("---------"); for(int i = 0; i < arrfast.Count; i++) Console.WriteLine(arrfast[i].Item1 + " + " + arrfast[i].Item2 + " = " + X); Console.ReadKey(); } } }
I implemented logic in Scala with out a Map. It gives duplicate pairs since the counter loops thru entire elements of the array. If duplicate pairs are needed, you can simply return the value pc val arr = Array[Int](8, 7, 2, 5, 3, 1, 5) val num = 10 var pc = 0 for(i <- arr.indices) { if(arr.contains(Math.abs(arr(i) - num))) pc += 1 } println(s"Pairs: ${pc/2}") It is working with duplicates values in the array as well.
GOLANG Implementation func findPairs(slice1 []int, sum int) [][]int { pairMap := make(map[int]int) var SliceOfPairs [][]int for i, v := range slice1 { if valuei, ok := pairMap[v]; ok { //fmt.Println("Pair Found", i, valuei) SliceOfPairs = append(SliceOfPairs, []int{i, valuei}) } else { pairMap[sum-v] = i } } return SliceOfPairs }
function findPairOfNumbers(arr, targetSum) { arr = arr.sort(); var low = 0, high = arr.length - 1, sum, result = []; while(low < high) { sum = arr[low] + arr[high]; if(sum < targetSum) low++; else if(sum > targetSum) high--; else if(sum === targetSum) { result.push({val1: arr[low], val2: arr[high]}); high--; } } return (result || false); } var pairs = findPairOfNumbers([1,2,3,4,5,6,7,8,9,0], 7); if(pairs.length) { console.log(pairs); } else { console.log("No pair of numbers found that sums to " + 7); }