How do you do this? The values are unsorted but are of [1..n]
Example array [3,1,2,5,7,8]
. Answer: 4, 6
I saw this solution in
#include <iostream>
using namespace std;
int main() {
int arr[]={3,1,2,5,7,8};
int n=6;
for(int i=0;i<n;i++){
if(arr[i]>0 && arr[i]<=n){
int temp=arr[i]-1;
if(arr[i]!=arr[temp]){
swap(arr[i],arr[temp]);
i--;
}
}
}
for(int i=0;i<n;i++){
if(arr[i]!=i+1)
cout<<i+1<<endl;
}
// your code goes here
return 0;
}
We can use the same array as a bucket. We traverse it once and keep on swapping the element to their correct index. If the value is less than 1 or more than array length, we leave it as it is. Initial Array- 3 1 2 5 7 8 swap(3,5) 5 1 2 3 7 8 swap(5,8) 8 1 2 3 7 5 After this we again traverse the array. The elements which are not in their proper position are missing hence we print the index. Time Complexity-O(n)
Code sample(Java) for @slider answer
/**
* get 2 missed numbers from randomly shuffled array of unique elements from [1,n]
*
* @param array - shuffled array of unique elements from [1,n], but 2 random elements was missed. len = n-2
* @return array with 2 missed elements
*/
public static int[] getMissedNumbers(int[] array) {
int sum = 0;
int fullSum = 0;
int fullProduct = 1;
int product = 1;
for (int i = 0; i < array.length + 2; i++) {
int currNaturalNumber = i + 1;
fullSum = fullSum + currNaturalNumber;
fullProduct = fullProduct * currNaturalNumber;
if (i < array.length) {
sum = sum + array[i];
product = product * array[i];
}
}
int missedSum = fullSum - sum; //firstMissedNum + secondMissedNum
int missedProduct = fullProduct / product; //firstMissedNum * secondMissedNum
//ax*x + bx + c = 0
//x = (-b +- sqrt(b*b - 4*a*c))/2*a
// -b = missedSum , c = missedProduct, a = 1
Double firstMissedNum = (missedSum + Math.sqrt(missedSum * missedSum - 4 * missedProduct)) / 2;
Double secondMissedNum = (missedSum - Math.sqrt(missedSum * missedSum - 4 * missedProduct)) / 2;
return new int[]{firstMissedNum.intValue(), secondMissedNum.intValue()};
}
and simple arrays generator for tests
public static Map.Entry<int[], int[]> generateArray(int maxN, int missedNumbersCount) {
int[] initialArr = new int[maxN];
for (int i = 0; i < maxN; i++) {
initialArr[i] = i + 1;
}
shuffleArray(initialArr);
int[] skippedNumbers = Arrays.copyOfRange(initialArr, maxN - missedNumbersCount, maxN);
int[] arrayWithoutSkippedNumbers = Arrays.copyOf(initialArr, maxN - missedNumbersCount);
return new AbstractMap.SimpleEntry<>(arrayWithoutSkippedNumbers, skippedNumbers);
}
private static void shuffleArray(int[] ar) {
Random rnd = ThreadLocalRandom.current();
for (int i = ar.length - 1; i > 0; i--) {
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
Starting with
x+y == SUM
xy == PRODUCT
There are two cases. If PRODUCT is zero, then one number is 0
and the other is SUM
. Otherwise both are non-zero; we can multiply the first equation by x
without changing the equality:
x*x + xy == x*SUM
Substitute the second equation:
x*x + PRODUCT = x*SUM
and rearrange in the usual form
x*x - x*SUM + PRODUCT = 0
So that
x = SUM/2 + sqrt(SUM*SUM - 4*PRODUCT)/2
y = SUM/2 - sqrt(SUM*SUM - 4*PRODUCT)/2
Java implementation: (Based on @Ben Voigt)
BigInteger fact=1;
int sum=0;
int prod=1;
int x,y; // The 2 missing numbers
int n=a.length;
int max=MIN_VALUE;
for (int i=0; i<a.length;i++){
sum+=a[i]; //sums the existing numbers
prod*=a[i]; //product the existing numbers
if (max<a[i]) //searches for the biggest number in the array
max=a[i];
}
while(max!=1){ //factorial for the maximum number
fact*=max;
max--;
}
sum=(n*(n+1))/2 - sum; //the sum of the 2 missing numbers
prod=fact/prod; //the product of the 2 missing numbers
x=sum/2 + Math.sqrt(sum*sum - 4*prod)/2;
y=sum/2 - Math.sqrt(sum*sum - 4*prod)/2;
I hope this program is useful to you all, i took the limit till 10 it can be done the same way, just use n as the limit and perform the same operations.
#include <iostream>
#include<math.h>
using namespace std;
int main()
{
int i,x[100],sum1=0,sum2=0,prod1=1,prod2=1,k,j,p=0;
cout<<"Enter 8 elements less than 10, they should be non recurring"<<endl;
for(i=0;i<8;i++)
{
cin>>x[i];
}
sum1=((10)*(11))/2;
for(i=0;i<8;i++)
{
sum2+=x[i];
}
k=sum1-sum2;
for(i=1;i<10;i++)
{
prod1=prod1*i;
}
for(i=0;i<8;i++)
{
prod2=prod2*x[i];
}
j=prod1/prod2;
p=sqrt((k*k)-(4*j));
cout<<"One missing no:"<<p/2<<endl;
cout<<"Second missing no:"<<k-p/2<<endl;
}
works for any number of missing elements: you can format the code a little .. but it works on duplicate and non duplicate entries also:
public static void main(String args[] ) throws Exception {
Scanner input = new Scanner(System.in);
System.out.println("Enter no. of students in the class");
int N = input.nextInt();
List<Integer> l = new ArrayList<Integer>();
int Nn=N;
System.out.println("Enter the roll numbers");
for(int i=0;i<Nn;i++)
{
int enter=input.nextInt();
l.add(enter);
}
Collections.sort(l);
Integer listarr[]=new Integer[l.size()];
listarr =l.toArray(listarr);
int check=0;
int m1[]=new int[N];
for(int i=0;i<N;i++)
{
m1[i]=i+1;
}
for (int i = 0; i < N; i++) {
boolean flag=false;
{
for (int j = 0; j < listarr.length; j++) {
if(m1[i]==listarr[j])
{
flag=true;
break;
}
else
{
flag=false;
}
}
if(flag==false)
{
System.out.println("Missing number Found : " + m1[i]);
}
}
}