what is the fastest way to find the gcd of n numbers? - algorithm

what is the fastest way to compute the greatest common divisor of n numbers?

Without recursion:
int result = numbers[0];
for(int i = 1; i < numbers.length; i++){
result = gcd(result, numbers[i]);
}
return result;
For very large arrays, it might be faster to use the fork-join pattern, where you split your array and calculate gcds in parallel. Here is some pseudocode:
int calculateGCD(int[] numbers){
if(numbers.length <= 2){
return gcd(numbers);
}
else {
INVOKE-IN-PARALLEL {
left = calculateGCD(extractLeftHalf(numbers));
right = calculateGCD(extractRightHalf(numbers));
}
return gcd(left,right);
}
}

You may want to sort the numbers first and compute the gcd recursively starting from the smallest two numbers.

C++17
I have written this function for calculating gcd of n numbers by using C++'s inbuilt __gcd(int a, int b) function.
int gcd(vector<int> vec, int vsize)
{
int gcd = vec[0];
for (int i = 1; i < vsize; i++)
{
gcd = __gcd(gcd, vec[i]);
}
return gcd;
}
To know more about this function visit this link .
Also refer to Dijkstra's GCD algorithm from the following link. It works without division. So it could be slightly faster (Please correct me if I am wrong.)

You should use Lehmer's GCD algorithm.

How about the following using Euclidean algorithm by subtraction:
function getGCD(arr){
let min = Math.min(...arr);
let max= Math.max(...arr);
if(min==max){
return min;
}else{
for(let i in arr){
if(arr[i]>min){
arr[i]=arr[i]-min;
}
}
return getGCD(arr);
}
}
console.log(getGCD([2,3,4,5,6]))
The above implementation takes O(n^2) time. There are improvements that can be implemented but I didn't get around trying these out for n numbers.

If you have a lot of small numbers, factorization may be actually faster.
//Java
int[] array = {60, 90, 45};
int gcd = 1;
outer: for (int d = 2; true; d += 1 + (d % 2)) {
boolean any = false;
do {
boolean all = true;
any = false;
boolean ready = true;
for (int i = 0; i < array.length; i++) {
ready &= (array[i] == 1);
if (array[i] % d == 0) {
any = true;
array[i] /= d;
} else all = false;
}
if (all) gcd *= d;
if (ready) break outer;
} while (any);
}
System.out.println(gcd);
(works for some examples, but not really tested)

Use the Euclidean algorithm :
function gcd(a, b)
while b ≠ 0
t := b;
b := a mod b;
a := t;
return a;
You apply it for the first two numbers, then the result with the third number, etc... :
read(a);
read(b);
result := gcd(a, b);
i := 3;
while(i <= n){
read(a)
result := gcd(result, a);
}
print(result);

Here below is the source code of the C program to find HCF of N numbers using Arrays.
#include<stdio.h>
int main()
{
int n,i,gcd;
printf("Enter how many no.s u want to find gcd : ");
scanf("%d",&n);
int arr[n];
printf("\nEnter your numbers below :- \n ");
for(i=0;i<n;i++)
{
printf("\nEnter your %d number = ",i+1);
scanf("%d",&arr[i]);
}
gcd=arr[0];
int j=1;
while(j<n)
{
if(arr[j]%gcd==0)
{
j++;
}
else
{
gcd=arr[j]%gcd;
i++;
}
}
printf("\nGCD of k no.s = %d ",gcd);
return 0;
}
For more refer to this website for further clarification.......

You can use divide and conquer. To calculate gcdN([]), you divide the list into first half and second half. if it only has one num for each list. you calculate using gcd2(n1, n2).
I just wrote a quick sample code. (assuming all num in the list are positive Ints)
def gcdN(nums):
n = len(nums)
if n == 0: return "ERROR"
if n == 1: return nums[0]
if n >= 2: return gcd2(gcdN(nums[:n//2]), gcdN(nums[n//2:]))
def gcd2(n1, n2):
for num in xrange(min(n1, n2), 0, -1):
if n1 % num == 0 and n2 % num == 0:
return num

Here's a gcd method that uses the property that gcd(a, b, c) = gcd(a, gcd(b, c)).
It uses BigInteger's gcd method since it is already optimized.
public static BigInteger gcd(BigInteger[] parts){
BigInteger gcd = parts[0];
for(int i = 1; i < parts.length; i++)
gcd = parts[i].gcd(gcd);
return gcd;
}

//Recursive solution to get the GCD of Two Numbers
long long int gcd(long long int a,long long int b)<br>
{
return b==0 ? a : gcd(b,a%b);
}
int main(){
long long int a,b;
cin>>a>>b;
if(a>b) cout<<gcd(a,b);
else cout<<gcd(b,a);
return 0;
}

import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
class GCDArray{
public static int [] extractLeftHalf(int [] numbers)
{
int l =numbers.length/2;
int arr[] = Arrays.copyOf(numbers, l+1);
return arr;
}
public static int [] extractRightHalf(int [] numbers)
{
int l =numbers.length/2;
int arr[] = Arrays.copyOfRange(numbers,l+1, numbers.length);
return arr;
}
public static int gcd(int[] numbers)
{
if(numbers.length==1)
return numbers[0];
else {
int x = numbers[0];
int y = numbers[1];
while(y%x!=0)
{
int rem = y%x;
y = x;
x = rem;
}
return x;
}
}
public static int gcd(int x,int y)
{
while(y%x!=0)
{
int rem = y%x;
y = x;
x = rem;
}
return x;
}
public static int calculateGCD(int[] numbers){
if(numbers.length <= 2){
return gcd(numbers);
}
else {
int left = calculateGCD(extractLeftHalf(numbers));
int right = calculateGCD(extractRightHalf(numbers));
return gcd(left,right);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[] = new int[n];
for(int i=0;i<n;i++){
arr[i]=sc.nextInt();
}
System.out.println(calculateGCD(arr));
}
}
**
Above is the java working code ..... the pseudo code of which is
already mention by https://stackoverflow.com/users/7412/dogbane
**

A recursive JavaScript (ES6) one-liner for any number of digits.
const gcd = (a, b, ...c) => b ? gcd(b, a % b, ...c) : c.length ? gcd(a, ...c) : Math.abs(a);

This is what comes off the top of my head in Javascript.
function calculateGCD(arrSize, arr) {
if(!arrSize)
return 0;
var n = Math.min(...arr);
for (let i = n; i > 0; i--) {
let j = 0;
while(j < arrSize) {
if(arr[j] % i === 0) {
j++;
}else {
break;
}
if(j === arrSize) {
return i;
}
}
}
}
console.log(generalizedGCD(4, [2, 6, 4, 8]));
// Output => 2

Here was the answer I was looking for.
The best way to find the gcd of n numbers is indeed using recursion.ie gcd(a,b,c)=gcd(gcd(a,b),c). But I was getting timeouts in certain programs when I did this.
The optimization that was needed here was that the recursion should be solved using fast matrix multiplication algorithm.

Related

How to add memoization in subset sum?

I am trying to solve subset sum problem with recursive solution, but to make to make it a bit more efficient I am trying to put memoization in it. However the code without memoization gives correct solution but with memoization it doesn't work properly.
public int subsetSum(int num[], int idx, int expecedSum, int dp[]) {
if (expecedSum == 0) {
return 1;
}
else if (idx < 0 || expecedSum < 0) {
return 0;
}
else {
if (dp[expecedSum] == -1) {
int x = subsetSum(num, idx - 1, expecedSum, dp);
int y = subsetSum(num, idx - 1, expecedSum - num[idx], dp);
dp[expecedSum] = (x == 1 || y == 1) ? 1 : 0;
}
return dp[expecedSum];
}
}
public static void main(String args[]) {
Solution s = new Solution();
int num[] = new int[]{1, 2, 3, 4, 5, 6, 7};
int sum = 0;
int n = new Scanner(System.in).nextInt();
int dp[] = new int[n + 1];
for (int i = 0; i < dp.length; i++) {
dp[i] = -1;
}
dp[0] = 1;
s.subsetSum(num, num.length - 1, n, dp);
}
Can someone help me with why this is not working?
If I enter n = 14 then ideally dp[14] should contains 1 but it doesn't contain 1.
The sum is not sufficient to describe the state. The pair (sum, index) is. If you make dp an array of arrays of size (max_sum + 1) x num.length and apply memoization for a pair (idx, expectedSum) in the subsetSet method, it works.
It has been years but this may help someone today.
The idea is to take both the state - means once with including current element into the sum and once excluding current element into the sum. and then taking OR(||) for those values and store in the cache.
the code will look something like this -
#include <iostream>
#include <vector>
using namespace std;
bool sumExists(vector<int> & a, int cursum, int n, vector<vector<int>> &dp) {
if(n==0 && cursum != 0)
return 0;
if(cursum==0)
return 1;
if(dp[n][cursum] != -1) {
return dp[n][cursum];
}
int newsum = cursum - a[n-1];
bool returnval = false;
if(newsum>=0) {
dp[n][newsum] = sumExists(a, newsum, n-1, dp);
dp[n][cursum] = sumExists(a, cursum, n-1, dp);
returnval = dp[n][newsum] || dp[n][cursum];
} else {
dp[n][cursum] = sumExists(a, cursum, n-1, dp);
returnval = dp[n][cursum];
}
return returnval;
}
int main() {
// your code goes here
vector<int> a{2,0,7,8,10};
int n = a.size();
int sum = 11;
vector<vector<int>> dp(n+1, vector<int>(sum+1, -1));
for(int i=0;i<=n;++i) {
dp[i][0]=true;
}
for(int i=1;i<=sum;++i) {
dp[0][i]=false;
}
if(sumExists(a, sum, n, dp)) {
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}

DP memoized approach for Longest common substring

can anyone provide the memoized approach for longest common substring between two strings.I know the bottom solution but I am not able to think in top-down manner.
Expected time complexity-O(n^2)
TOP-DOWN APPROACH
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
string X, Y; //input strings
int ans, dp[105][105]; // ans : answer
int LCS(int n, int m) //our function return value of (n,m) state
{ // so that we can use the result in (n+1,m+1) state
if(n == 0 || m == 0) return 0; //in case of match in (n+1,m+1) state
if(dp[n][m] != -1) return dp[n][m];
LCS(n-1,m); //to visit all n*m states (try example: X:ASDF
LCS(n,m-1); // we call these states first Y:ASDFF)
if(X[n-1] == Y[m-1])
{
dp[n][m] = LCS(n-1,m-1) + 1;
ans = max(ans, dp[n][m]);
return dp[n][m];
}
return dp[n][m] = 0;
}
int main()
{
int t; cin>>t;
while(t--)
{
int n, m; cin>>n>>m; //length of strings
cin>>X>>Y;
memset(dp, -1, sizeof dp);
ans = 0;
LCS(n, m);
cout<<ans<<'\n';
}
return 0;
}
Memoization with recursion works with top-down approach.
Taking LCS example using DP from Cormen into consideration below is the pseudo code describing how it will work.
MEMOIZED-LCS-LENGTH(X,Y)
m<-length[X]
n<-length[Y]
for(i<-1 to m)
do for(j<-1 to n)
c[i,j]<- -1
for(i<-1 to m)
c[i,0]<-0
for(j<-1 to n)
c[0,j]<-0
return RECURSIVE-LCS-LENGTH(X,Y,1,1)
RECURSIVE-LCS-LENGTH(X,Y,i,j)
if(c[i,j]!=-1)
return c[i,j]
//Above 2 line fetches the result if already present, instead of computing it again.
if(x[i]==y[j])
then c[i,j]<-RECURSIVE-LCS-LENGTH(X,Y,i+1,j+1)+1
else
c1<- RECURSIVE-LCS-LENGTH(X,Y,i+1,j)
c2<-RECURSIVE-LCS-LENGTH(X,Y,i,j+1)
if(c1<c2)
then c[i,j]<-c1
else c[i,j]<-c2
return c[i,j]
Java Solution:
class Solution {
public int findLength(int[] A, int[] B) {
int[][] cache = new int[A.length][B.length];
Arrays.stream(cache).forEach(a->Arrays.fill(a,-1));
int[] res = new int[1];
findLength(0, 0, A, B, cache, res);
return res[0];
}
public static int findLength(int a, int b, int[] A, int[] B, int[][] cache, int[] res){
if( a >= A.length || b >= B.length )
return 0;
if(cache[a][b] != -1){
return cache[a][b];
}
if(A[a] == B[b]){
cache[a][b] = 1 + findLength(a+1,b+1,A,B,cache,res);
// remember you can not return here: why? see case: s1 = 1,2,3 s2=1,4,1,2,3
}
// try out other possiblities and update cache
findLength(a+1,b,A,B,cache,res);
findLength(a,b+1,A,B,cache,res);
//you can avoid this and find max value at end in cache
res[0] = Math.max(res[0],cache[a][b]);
//at this point cache might have -1 or updated value, if its -1 make it to 0 as this location is visited and no common substring is there from here
cache[a][b] = Math.max(0,cache[a][b]);
return cache[a][b];
}
}
Recursion plus memoization in python. Please note this code is partially accepted on Hackerearth and Geeksforgeeks.For larger test cases, it is giving MLE.
import sys
sys.setrecursionlimit(1000000)
maxlen=0
t=None
def solve(s1, s2, n, m):
global maxlen, t
if n<=0 or m<=0:
return 0
if t[n][m]!=-1:
return t[n][m]
if s1[n-1]==s2[m-1]:
temp=1+solve(s1, s2, n-1, m-1)
maxlen=max(maxlen, temp)
t[n][m]=temp
return temp
t[n][m]=0
return 0
class Solution:
def longestCommonSubstr(self, S1, S2, n, m):
global maxlen, t
maxlen=0
t=[[-1]*(m+1) for i in range(n+1)]
for i in range(n+1):
for j in range(m+1):
solve(S1, S2, i, j)
return maxlen
if __name__=='__main__':
S1=input().strip()
S2=input().strip()
n=len(S1)
m=len(S2)
ob = Solution()
print(ob.longestCommonSubstr(S1, S2, n, m))
An easy solution is described below. Here memo[n][m] does not store the length of
greatest substring but you can store the greatest substring in pointer maxi as follows:
#include<iostream>
#include<string>
using namespace std;
int lcs(string X,string Y,int n,int m,int *maxi,int memo[][8]) {
if(n==0||m==0) {
return 0;
}
int k=0;
int j=0;
if(memo[n-1][m-1]!=-1) {
return memo[n-1][m-1];
}
if(X[n-1]==Y[m-1]) {
memo[n-1][m-1] = 1+lcs(X,Y,n-1,m-1,maxi,memo);
if(*maxi<memo[n-1][m-1])
*maxi=memo[n-1][m-1];
}
else {
memo[n-1][m-1]=0;
}
int l = lcs(X,Y,n-1,m,maxi,memo);
int i = lcs(X,Y,n,m-1,maxi,memo);
return memo[n-1][m-1];
}
int main()
{
int n,m;
string X = "abcdxyze";
//string X = "abcd";
string Y = "xyzabcde";
n=X.length();
m=Y.length();
int memo[n][8];
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
memo[i][j]=-1;
}
}
int maxi=0;
int k = lcs(X,Y,n,m,&maxi,memo);
cout << maxi;
return 0;
}
class Solution {
public:
int t[1005][1005];
int maxC = 0;
int recur_memo(vector<int>& nums1, vector<int>& nums2, int m, int n) {
if(t[m][n] != -1)
return t[m][n];
if(m == 0 || n == 0)
return 0;
int max_substring_ending_here = 0;
//Example : "abcdezf" "abcdelf"
//You see that wowww, string1[m-1] = string2[n-1] = 'f' and you happily
go for (m-1, n-1)
//But you see, in future after a gap of 'l' and 'z', you will find
"abcde" and "abcde"
if(nums1[m-1] == nums2[n-1]) {
max_substring_ending_here = 1 + recur_memo(nums1, nums2, m-1, n-1);
}
//May be you find better results if you do (m-1, n) and you end up
updating maxC with some LAAARGEST COMMON SUBSTRING LENGTH
int decrease_m = recur_memo(nums1, nums2, m-1, n); //stage (m-1, n)
//OR,
//May be you find better results if you do (m, n-1) and you end up
updating maxC with some LAAARGEST COMMON SUBSTRING LENGTH
int decrease_n = recur_memo(nums1, nums2, m, n-1); //stage (m, n-1)
//Like I said, you need to keep on finding the maxC in every call you
make throughout your journey.
maxC = max({maxC, max_substring_ending_here, decrease_m, decrease_n});
//BUT BUT BUT, you need to return the best you found at this stage (m, n)
return t[m][n] = max_substring_ending_here;
}
int findLength(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size();
int n = nums2.size();
memset(t, -1, sizeof(t));
recur_memo(nums1, nums2, m, n); //resurive+memoization
return maxC;
}
};
Link : https://leetcode.com/problems/maximum-length-of-repeated-subarray/discuss/1169215/(1)-Recursive%2BMemo-(2)-Bottom-Up-(C%2B%2B)
Here is a recursive and top-down approach:
public int lcsSubstr(char[] s1, char[] s2, int m, int n, int c) {
if (m == 0 || n == 0) {
return c;
}
if (s1[m-1] == s2[n-1]) {
c = lcsSubstr(s1, s2, m-1, n-1, c+1);
} else {
c2 = Math.max(lcsSubstr(s1, s2, m, n - 1, 0), lcsSubstr(s1, s2, m-1, n, 0));
}
return Math.max(c, c2);
}
public int lcsSubstrMemo(char[] s1, char[] s2, int m, int n, int c, int[][] t) {
if(m == 0 || n == 0) {
return c;
}
if (t[m-1][n-1] != -1) return t[m-1][n-1];
if(s1[m - 1] == s2[n - 1]) {
c = lcsSubstr(s1, s2, m - 1, n - 1, c + 1);
} else {
c2 = Math.max(lcsSubstr(s1, s2, m, n - 1, 0), lcsSubstr(s1, s2, m - 1, n, 0));
}
t[m - 1][n - 1] = Math.max(c, c2);
return t[m-1][n-1];
}
Memoization refers to caching the solutions to subproblems in order to use them later. In the longest common subsequence problem, you try to match substrings of two subsequences to see if they match, maintaining in memory the longest one yet found. Here is the solution in Java you are looking for (memoized version of LCS):
public class LongestCommonSubsequence {
private static HashMap<Container, Integer> cache = new HashMap<>();
private static int count=0, total=0;
public static void main(String sargs[]){
Scanner scanner = new Scanner(System.in);
String x=scanner.nextLine();
String y=scanner.nextLine();
int max=0;
String longest="";
for(int j=0;j<x.length();j++){
String common=commonSubsequence(j,0, x, y);
if(max<common.length()){
max=common.length();
longest=common;
}
}
for(int j=0;j<y.length();j++){
String common=commonSubsequence(j,0, y, x);
if(max<common.length()){
max=common.length();
longest=common;
}
}
System.out.println(longest);
System.out.println("cache used "+count+" / "+total);
}
public static String commonSubsequence(final int startPositionX, int startPositionY, String x, String y){
StringBuilder commonSubsequence= new StringBuilder();
for(int i=startPositionX;i<x.length();i++){
Integer index=find(x.charAt(i),startPositionY,y);
if(index!=null){
commonSubsequence.append(x.charAt(i));
if(index!=y.length()-1)
startPositionY=index+1;
else
break;
}
}
return commonSubsequence.toString();
}
public static Integer find(char query, int startIndex, String target){
Integer pos=cache.get(new Container(query, startIndex));
total++;
if(pos!=null){
count++;
return pos;
}else{
for(int i=startIndex;i<target.length();i++){
if(target.charAt(i)==query){
cache.put(new Container(query, startIndex), i);
return i;
}
}
return null;
}
}
}
class Container{
private Character toMatch;
private Integer indexToStartMatch;
public Container(char t, int i){
toMatch=t;
indexToStartMatch=i;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime
* result
+ ((indexToStartMatch == null) ? 0 : indexToStartMatch
.hashCode());
result = prime * result + ((toMatch == null) ? 0 : toMatch.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Container other = (Container) obj;
if (indexToStartMatch == null) {
if (other.indexToStartMatch != null)
return false;
} else if (!indexToStartMatch.equals(other.indexToStartMatch))
return false;
if (toMatch == null) {
if (other.toMatch != null)
return false;
} else if (!toMatch.equals(other.toMatch))
return false;
return true;
}
}

Missing integer variation - O(n) solution needed [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
The problem comes from Codility programming training and it sounds as follows:
we have an array (A[]) with n (ranging from 1 to 100,000) elements and these are our parameters. The elements of the array are integers from −2,147,483,648 to 2,147,483,647, and we need to find smallest positive integer that is NOT in the array. Of course this could be done easily in O(n*log n) by sorting them all and going through the sorted array, looking for the missing posiitve number (this last operation has O(n) worst time complexity in my solution). But according to Codility, this ENTIRE problem can be done in O(n), and I cannot see any way to do that. Could someone give some tips to let me get un-stuck?
PS Here is a link to detailed description of the problem which I'm not allowed to copy - https://codility.com/c/intro/demo35UEXH-EAT
By pigeonhole principle, at least one of the numbers 1, 2, ..., n+1 is not in the array.
Let us create a boolean array b of size n+1 to store whether each of these numbers is present.
Now, we process the input array. If we find a number from 1 to n+1, we mark the corresponding entry in b. If the number we see does not fit into these bounds, just discard it and proceed to the next one. Both cases are O(1) per input entry, total O(n).
After we are done processing the input, we can find the first non-marked entry in our boolean array b trivially in O(n).
Simple solution 100% in Java.
Please note it is O(nlogn) solution but gives 100% result in codility.
public static int solution(final int[] A)
{
Arrays.sort(A);
int min = 1;
// Starting from 1 (min), compare all elements, if it does not match
// that would the missing number.
for (int i : A) {
if (i == min) {
min++;
}
}
return min;
}
wrote this today and got 100/100. not the most elegant solution, but easy to understand -
public int solution(int[] A) {
int max = A.length;
int threshold = 1;
boolean[] bitmap = new boolean[max + 1];
//populate bitmap and also find highest positive int in input list.
for (int i = 0; i < A.length; i++) {
if (A[i] > 0 && A[i] <= max) {
bitmap[A[i]] = true;
}
if (A[i] > threshold) {
threshold = A[i];
}
}
//find the first positive number in bitmap that is false.
for (int i = 1; i < bitmap.length; i++) {
if (!bitmap[i]) {
return i;
}
}
//this is to handle the case when input array is not missing any element.
return (threshold+1);
}
public int solutionMissingInteger(int[] A) {
int solution = 1;
HashSet<Integer> hashSet = new HashSet<>();
for(int i=0; i<A.length; ++i){
if(A[i]<1) continue;
if(hashSet.add(A[i])){
//this int was not handled before
while(hashSet.contains(solution)){
solution++;
}
}
}
return solution;
}
Simple Java soution. Scored 100/100 in correctness and performance.
public int solution(int[] A) {
int smallestMissingInteger = 1;
if (A.length == 0) {
return smallestMissingInteger;
}
Set<Integer> set = new HashSet<Integer>();
for (int i = 0; i < A.length; i++) {
if (A[i] > 0) {
set.add(A[i]);
}
}
while (set.contains(smallestMissingInteger)) {
smallestMissingInteger++;
}
return smallestMissingInteger;
}
Build a hash table of all the values. For the numbers 1 to n + 1, check if they are in the hash table. At least one of them is not. Print out the lowest such number.
This is O(n) expected time (you can get with high probability). See #Gassa's answer for how to avoid the hash table in favor of a lookup table of size O(n).
JavaScript 100%
function solution(A) {
let sortedOb = {};
let biggest = 0;
A.forEach(el => {
if (el > 0) {
sortedOb[el] = 0;
biggest = el > biggest ? el : biggest;
}
});
let arr = Object.keys(sortedOb).map(el => +el);
if (arr.length == 0) return 1;
for(let i = 1; i <= biggest; i++) {
if (sortedOb[i] === undefined) return i;
}
return biggest + 1;
}
100% Javascript
function solution(A) {
// write your code in JavaScript (Node.js 4.0.0)
var max = 0;
var array = [];
for (var i = 0; i < A.length; i++) {
if (A[i] > 0) {
if (A[i] > max) {
max = A[i];
}
array[A[i]] = 0;
}
}
var min = max;
if (max < 1) {
return 1;
}
for (var j = 1; j < max; j++) {
if (typeof array[j] === 'undefined') {
return j
}
}
if (min === max) {
return max + 1;
}
}
C# scored 100%,
Explanation: use of lookup table where we store already seen values from input array, we only care about values that are greater than 0 and lower or equal than length on input array
public static int solution(int[] A)
{
var lookUpArray = new bool[A.Length];
for (int i = 0; i < A.Length; i++)
if (A[i] > 0 && A[i] <= A.Length)
lookUpArray[A[i] - 1] = true;
for (int i = 0; i < lookUpArray.Length; i++)
if (!lookUpArray[i])
return i + 1;
return A.Length + 1;
}
This is my solution is Swift 4
public func solution(_ A: inout [Int]) -> Int {
var minNum = 1
var hashSet = Set<Int>()
for int in A {
if int > 0 {
hashSet.insert(int)
}
}
while hashSet.contains(minNum) {
minNum += 1
}
return minNum
}
var array = [1,3,6]
solution(&array)
// Answer: 2
100%: the Python sort routine is not regarded as cheating...
def solution(A):
"""
Sort the array then loop till the value is higher than expected
"""
missing = 1
for elem in sorted(A):
if elem == missing:
missing += 1
if elem > missing:
break
return missing
It worked for me. It is not O(n), but little simpler:
import java.util.stream.*;
class Solution {
public int solution(int[] A) {
A = IntStream.of(A)
.filter(x->x>0)
.distinct()
.sorted()
.toArray();
int min = 1;
for(int val : A)
{
if(val==min)
min++;
else
return min;
}
return min;
}
}
My solution. 100%. In Java.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Solution {
public int solution(int[] A) {
Arrays.sort(A);
ArrayList<Integer> positive = new ArrayList<>();
for (int i = 0; i < A.length; i++) {
if(A[i] > 0)
positive.add(A[i]);
}
if(positive.isEmpty()) return 1;
if(positive.get(0) > 1) return 1;
for(int i = 0; i < positive.size() - 1; i++) {
if(positive.get(i + 1) - positive.get(i) > 1)
return positive.get(i) + 1;
}
return positive.get(positive.size() - 1) + 1;
}
public static void main(String[] args) {
Solution solution = new Solution();
int[] A = {-5,1,2,3,4,6,7,8,9,5};
System.out.println(solution.solution(A));
}
}
javascript 100% 100%
first sort the array, you just need to scan positive elements so find index of 1 (if there is no 1 in array then answer is 1). then search elements after 1 till find missing number.
function solution(A) {
// write your code in JavaScript (Node.js 6.4.0)
var missing = 1;
// sort the array.
A.sort(function(a, b) { return a-b });
// try to find the 1 in sorted array if there is no 1 so answer is 1
if ( A.indexOf(1) == -1) { return 1; }
// just search positive numbers to find missing number
for ( var i = A.indexOf(1); i < A.length; i++) {
if ( A[i] != missing) {
missing++;
if ( A[i] != missing ) { return missing; }
}
}
// if cant find any missing number return next integer number
return missing + 1;
}
I believe the solution is more involved than 'marking' corresponding values using a boolean array of n (100,000) elements. The boolean array of size n will not 'directly' map to the possible range of values (−2,147,483,648 to 2,147,483,647).
This Java example I wrote attempts to map the 100K rows by mapping the value based on their offset from the max value. It also performs a modulus to reduce the resulting array to the same size as the sample element length.
/**
*
* This algorithm calculates the values from the min value and mods this offset with the size of the 100K sample size.
* This routine performs 3 scans.
* 1. Find the min/max
* 2. Record the offsets for the positive integers
* 3. Scan the offsets to find missing value.
*
* #author Paul Goddard
*
*/
public class SmallestPositiveIntMissing {
static int ARRAY_SIZE = 100000;
public static int solve(int[] array) {
int answer = -1;
Maxmin maxmin = getMaxmin(array);
int range = maxmin.max - maxmin.min;
System.out.println("min: " + maxmin.min);
System.out.println("max: " + maxmin.max);
System.out.println("range: " + range);
Integer[] values = new Integer[ARRAY_SIZE];
if (range == ARRAY_SIZE) {
System.out.println("No gaps");
return maxmin.max + 1;
}
for (int val: array) {
if (val > 0) {
int offset = val - maxmin.min;
int index = offset % ARRAY_SIZE;
values[index] = val;
}
}
for (int i = 0; i < ARRAY_SIZE; i++) {
if (values[i] == null) {
int missing = maxmin.min + i;
System.out.println("Missing: " + missing);
answer = missing;
break;
}
}
return answer;
}
public static Maxmin getMaxmin(int[] array) {
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int val:array) {
if (val >=0) {
if (val > max) max = val;
if (val < min) min = val;
}
}
return new Maxmin(max,min);
}
public static void main(String[] args) {
int[] A = arrayBuilder();
System.out.println("Min not in array: " + solve(A));
}
public static int[] arrayBuilder() {
int[] array = new int[ARRAY_SIZE];
Random random = new Random();
System.out.println("array: ");
for (int i=0;i < ARRAY_SIZE; i++) {
array[i] = random.nextInt();
System.out.print(array[i] + ", ");
}
System.out.println(" array done.");
return array;
}
}
class Maxmin {
int max;
int min;
Maxmin(int max, int min) {
this.max = max;
this.min = min;
}
}
Sweet Swift version. 100% correct
public func solution(inout A : [Int]) -> Int {
//Create a Hash table
var H = [Int:Bool]()
// Create the minimum possible return value
var high = 1
//Iterate
for i in 0..<A.count {
// Get the highest element
high = A[i] > high ? A[i] : high
// Fill hash table
if (A[i] > 0){
H[A[i]] = true
}
}
// iterate through possible values on the hash table
for j in 1...high {
// If you could not find it on the hash, return it
if H[j] != true {
return j
} else {
// If you went through all values on the hash
// and can't find it, return the next higher value
// e.g.: [1,2,3,4] returns 5
if (j == high) {
return high + 1
}
}
}
return high
}
int[] copy = new int[A.length];
for (int i : A)
{
if (i > 0 && i <= A.length)
{
copy[i - 1] = 1;
}
}
for (int i = 0; i < copy.length; i++)
{
if (copy[i] == 0)
{
return i + 1;
}
}
return A.length + 1;
Swift 3 - 100%
public func solution(_ A : inout [Int]) -> Int {
// write your code in Swift 3.0 (Linux)
var solution = 1
var hashSet = Set<Int>()
for int in A
{
if int > 0
{
hashSet.insert(int)
while hashSet.contains(solution)
{
solution += 1
}
}
}
return solution
}
Thanks to Marian's answer above.
This is my solution using python:
def solution(A):
m = max(A)
if m <= 0:
return 1
if m == 1:
return 2
# Build a sorted list with all elements in A
s = sorted(list(set(A)))
b = 0
# Iterate over the unique list trying to find integers not existing in A
for i in xrange(len(s)):
x = s[i]
# If the current element is lte 0, just skip it
if x <= 0:
continue;
b = b + 1
# If the current element is not equal to the current position,
# it means that the current position is missing from A
if x != b:
return b
return m + 1
Scored 100%/100% https://codility.com/demo/results/demoDCU7CA-SBR/
Create a binary array bin of N+1 length (C uses 0 based indexing)
Traverse the binary array O(n)
If A[i] is within the bounds of bin then mark bin entry at index A[i] as present or true.
Traverse the binary array again
Index of any bin entry that is not present or false is your missing integer
~
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
int solution(int A[], int N) {
// write your code in C99 (gcc 6.2.0)
int i;
bool *bin = (bool *)calloc((N+1),sizeof(bool));
for (i = 0; i < N; i++)
{
if (A[i] > 0 && A[i] < N+1)
{
bin[A[i]] = true;
}
}
for (i = 1; i < N+1; i++)
{
if (bin[i] == false)
{
break;
}
}
return i;
}
May be helpful, I am using arithmetic progression to calculate the sum, and using binary searach the element is fetched. checked with array of couple of hundred values works good. As there is one for loop and itression in step of 2, O(n/2) or less
def Missingelement (A):
B = [x for x in range(1,max(A)+1,1)]
n1 = len(B) - 1
begin = 0
end = (n1)//2
result = 0
print(A)
print(B)
if (len(A) < len(B)):
for i in range(2,n1,2):
if BinSum(A,begin,end) > BinSum(B,begin,end) :
end = (end + begin)//2
if (end - begin) <= 1 :
result=B[begin + 1 ]
elif BinSum(A,begin,end) == BinSum(B,begin,end):
r = end - begin
begin = end
end = (end + r)
if begin == end :
result=B[begin + 1 ]
return result
def BinSum(C,begin,end):
n = (end - begin)
if end >= len(C):
end = len(C) - 1
sum = n*((C[begin]+C[end])/2)
return sum
def main():
A=[1,2,3,5,6,7,9,10,11,12,14,15]
print ("smallest number missing is ",Missingelement(A))
if __name__ == '__main__': main()
Code for C, in fact, this can be used for any programming language without any change in the logic.
Logic is sum of N number is N*(N+1)/2.
int solution(int A[], int N) {
// write your code in C99
long long sum=0;
long long i;
long long Nsum=0;
for(i=0;i<N;i++){
sum=sum + (long long)A[i];
}
if (N%2==0){
Nsum= (N+1)*((N+2)/2);
return (int)(Nsum-sum);
}
else{
Nsum= ((N+1)/2)*(N+2);
return (int)(Nsum-sum);
}
}
This gave the 100/100 score.
This solution gets 100/100 on the test:
class Solution {
public int solution(int[] A) {
int x = 0;
while (x < A.length) {
// Keep swapping the values into the matching array positions.
if (A[x] > 0 && A[x] <= A.length && A[A[x]-1] != A[x]) {
swap(A, x, A[x] - 1);
} else {
x++; // Just need to increment when current element and position match.
}
}
for (int y=0; y < A.length; y++) {
// Find first element that doesn't match position.
// Array is 0 based while numbers are 1 based.
if (A[y] != y + 1) {
return y + 1;
}
}
return A.length + 1;
}
private void swap (int[] a, int i, int j) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
100% in PHP https://codility.com/demo/results/trainingKFXWKW-56V/
function solution($A){
$A = array_unique($A);
sort($A);
if (empty($A)) return 1;
if (max($A) <= 0) return 1;
if (max($A) == 1) return 2;
if (in_array(1, $A)) {
$A = array_slice($A, array_search(1, $A)); // from 0 to the end
array_unshift($A, 0); // Explanation 6a
if ( max($A) == array_search(max($A), $A)) return max($A) + 1; // Explanation 6b
for ($i = 1; $i <= count($A); $i++){
if ($A[$i] != $i) return $i; // Explanation 6c
}
} else {
return 1;
}
}
// Explanation
remove all duplicates
sort from min to max
if the array is empty return 1
if max of array is zero or less, return 1
if max of array is 1, return 2 // next positive integer
all other cases:
6a) split the array from value 1 to the end and add 0 before first number
6b) if the value of last element of array is the max of array, then the array is ascending so we return max + 1 // next positive integer
6c) if the array is not ascending, we find a missing number by a function for: if key of element is not as value the element but it should be (A = [0=>0, 1=>1,2=>3,...]), we return the key, because we expect the key and value to be equal.
Here is my solution, it Yields 88% in evaluation- Time is O(n), Correctness 100%, Performance 75%. REMEMBER - it is possible to have an array of all negative numbers, or numbers that exceed 100,000. Most of the above solutions (with actual code) yield much lower scores, or just do not work. Others seem to be irrelevant to the Missing Integer problem presented on Codility.
int compare( const void * arg1, const void * arg2 )
{
return *((int*)arg1) - *((int*)arg2);
}
solution( int A[], int N )
{
// Make a copy of the original array
// So as not to disrupt it's contents.
int * A2 = (int*)malloc( sizeof(int) * N );
memcpy( A2, A1, sizeof(int) * N );
// Quick sort it.
qsort( &A2[0], N, sizeof(int), compare );
// Start out with a minimum of 1 (lowest positive number)
int min = 1;
int i = 0;
// Skip past any negative or 0 numbers.
while( (A2[i] < 0) && (i < N )
{
i++;
}
// A variable to tell if we found the current minimum
int found;
while( i < N )
{
// We have not yet found the current minimum
found = 0;
while( (A2[i] == min) && (i < N) )
{
// We have found the current minimum
found = 1;
// move past all in the array that are that minimum
i++;
}
// If we are at the end of the array
if( i == N )
{
// Increment min once more and get out.
min++;
break;
}
// If we found the current minimum in the array
if( found == 1 )
{
// progress to the next minimum
min++;
}
else
{
// We did not find the current minimum - it is missing
// Get out - the current minimum is the missing one
break;
}
}
// Always free memory.
free( A2 );
return min;
}
My 100/100 solution
public int solution(int[] A) {
Arrays.sort(A);
for (int i = 1; i < 1_000_000; i++) {
if (Arrays.binarySearch(A, i) < 0){
return i;
}
}
return -1;
}
static int spn(int[] array)
{
int returnValue = 1;
int currentCandidate = 2147483647;
foreach (int item in array)
{
if (item > 0)
{
if (item < currentCandidate)
{
currentCandidate = item;
}
if (item <= returnValue)
{
returnValue++;
}
}
}
return returnValue;
}

Analyzing an exponential recursive function

I am trying to calculate the complexity of the following
exponential recursive function.
The isMember() and isNotComputed() functions reduce the number
of recursive calls.
The output of this code is a set of A[], B[] which are printed at the
initial part of recursive function call.
Would appreciate any inputs on developing a recursive relationship for this
problem which would lead to the analysis of this program.
Without the functions isMember(), isNotComputed() this code has the complexity of O(2^N). Empirically (with the above two functions) this code has a complexity of O(|N^2||L|). Where L is the number of recursive calls made, i.e. results generated.
I am trying to calculate the complexity of this code as accurate as possible, so that I can compare the efficiency of this with a set of other algorithms which are similar in nature.
void RecuriveCall(int A[], int ASize, short int B[], int BSize,
int y, short int level) {
int C[OBJECTSIZE];
short int D[ATTRIBUTESIZE];
int CSize, DSize;
PrintResult( A,ASize, B, BSize);
for (int j=y; j<n; j++) {
if (! isMember(j, B, BSize)) {
function1(C,CSize,A,ASize,j);
function2(D,DSize,C, CSize);
if (isNotComputed(B, BSize, D, DSize, j)) {
RecursiveCall(C, CSize,D, DSize, j+1, level+1);
}
}
}
}
// Complexity - O(log N) - Binary Search
bool isMember(int j,short int B[], int BSize) {
int first, mid, last;
first = 0;
last = BSize-1;
if (B[first] == j || B[last] == j) {
return true;
}
mid = (first+last)/2;
while (first <= last) {
if (j == B[mid]) {
return true;
}
else if (j < B[mid])
last = mid-1;
else
first = mid+1;
mid = (first+last)/2;
}
return false;
}
// complexity - O(N)
bool isNotComputed(short int B[], int BSize, short int D[], int DSize,int j) {
if (j==0) {
return true;
}
int r = 0;
while (r<BSize && B[r]<j && r<DSize && D[r]<j) {
if (B[r] != D[r]) {
return false;
}
r=r+1;
}
// Now we can check if either B[] or D[] has extra elements which are < j
if (r<BSize && r < DSize && B[r]>=j && D[r] >=j) {// we know it is okay
return true;
}
if (r==BSize && r==DSize) {
return true;
}
if (r==BSize && r<DSize && D[r] >=j) {
return true;
}
if (r==DSize && r<BSize && B[r] >=j) {
return true;
}
return false;
}
// Complexity - O(N)
void function1(int C[],int &CSize,int A[] ,int ASize,int j) {
int tsize = 0;
for (int r=0;r<ASize;r++)
if (I[A[r]][j]==1)
C[tsize++] = A[r];
CSize = tsize;
}
// Complexity - O(|N||G|) - G - number of objects
void function2(short int B[], int &BSize,int A[], int ASize) {
int i,j;
int c=0;
// Iterate through all attributes
for (j = 0; j < MAXATTRIBUTES; ++j) {
// Iterate through all objects
for (i = 0; i < ASize; ++i)
if (!I[A[i]][j])
break;
if (i == ASize)
B[c++] = j;
}
BSize = c;
}
void main() {
n = MAXATTRIBUTES;
for (int r=0; r<MAXOBJECTS; r++)
A[r] = r;
ASize = MAXOBJECTS;
function2(B, BSize, A, ASize);
RecursiveCall(A, ASize,B, BSize, 0, 0);
}
The answer presented by "mohamed ennahdi el idrissi" addresses how a recursive relationship can be developed.
How do you incorporate the functions isMember() and isNotComputed() functions into this. In essence these reduce the number of recursive calls made significantly. Is there a way of introducing a probabilistic function to represent them? i.e P(f(n))xRecCall(n-1). I have seen the complexity of some algorithms been computed e.g. as O(N^2.48). How do you come with such values?
I have tried to adapt the following recurrence relation to your code, see the steps below:
Where n = MAXATTRIBUTES (constant), and m = ASize.

Numbers ending in 3 have at least one multiple having all ones

Hi Here is a Q that was asked in Adobe Interview.
Numbers ending in 3 have at least one multiple having all ones. for
eg., 3 and 13 have amultiples like 111 and 111111 respectively. Given
such a no. , find the smallest such multiple of that number. The
multiple can exceed the range of int, long. You cannot use any
complex data structure.
Can you provide me with an efficient solution
got the answer now :)
int count=1, rem=1;
while(rem)
{
rem= (rem*10+1)%n; count++;
}
while(count--){ cout<<"1";}
Here is an attempt to do it more efficiently that trying 1, 11, 111, 111.. Could this pay off. Is there a more elegant answer better than trying numbers one at a time?
Write the numbers 1, 11, 111, ... as (10^k - 1) / 9, where the division is known to be exact. Given a target number in the form 10x+3 we want to find the smallest k solving (10^k - 1) / 9 = Y(10x + 3) where Y is an integer. Look for small solutions of 10^k = 1 mod 9(10x + 3). This is http://en.wikipedia.org/wiki/Discrete_logarithm except that arithmetic mod 9(10x + 3) does not necessarily form a group - however the http://en.wikipedia.org/wiki/Baby-step_giant-step algorithm should still apply and could be used to search steadily increasing ranges of k, instead of searching possible values of k one at a time.
#include <iostream>
using namespace std;
int main() {
int t;
cin>>t;
while(t--){
long long n;
cin>>n;
long long cur = 1;
while(cur%n!=0){
cur = cur*10+1;
}
cout<<cur<<endl;
}
return 0;
}
Solution independent of output size:
public String ones(int n)
{
int i, m = 1;
String num="1";
for (i = 1; i <= n; i++) {
if (m == 0)
return num;
/* Solution found */
num=num+"1";
m = (10*m + 1) % n;
}
return null; /* No solution */
}
If you are looking for a Solution in Java, here it is
public static void main(String[] args) {
int input = 13; // this can be any number ending with 3
int minAllOnesNum = 1;
int nextAllOnesNum= minAllOnesNum;
int numberof1s=1;
int count = 0;
while(true)
{
count++;
if(nextAllOnesNum%input == 0 )
{
break;
}
nextAllOnesNum = nextAllOnesNum*10 + 1;
if(nextAllOnesNum>=input) {
nextAllOnesNum%=input;
}
numberof1s++;
}
System.out.println("Number of iterations : " + count);
for(int i=1; i<=numberof1s; i++) {
System.out.print("1");
}
}
If you are looking for a Solution in Java, here it is
public static void main(String[] args) {
int input = 55333;
int minAllOnesNum = 1;
int nextAllOnesNum= minAllOnesNum;
int numberof1s=1;
int count = 0;
while(true)
{
count++;
if(nextAllOnesNum%input == 0 )
{
break;
}
nextAllOnesNum = nextAllOnesNum*10 + 1;
if(nextAllOnesNum>=input) {
nextAllOnesNum%=input;
}
numberof1s++;
}
System.out.println("Number of Iterations: " + count);
for(int i=1; i<=numberof1s; i++) {
System.out.print("1");
}
}
static int findOnes(int num){
int i = 1 ;
int power = 0;
while (i % num != 0){
i = (i * (10^power)) + 1;
}
return i;
}

Resources