web-dev-qa-db-ja.com

2つの欠落値を持つ整数の配列から2つの欠落している数値を見つけます

これはどうやるんですか?値はソートされていませんが、[1..n]配列の例[3,1,2,5,7,8]。回答:4, 6

私はこの解決策を別の同様の post で見ましたが、最後のステップを理解していません:

  • 数S = a1 + ... + anの合計を求めます。
  • また、二乗和T =a1²+ ... +an²を求めます。
  • 合計はS '= 1 + ... + n = n(n + 1)/ 2でなければならないことを知っています
  • 二乗和はT '=1²+ ... +n²= n(n + 1)(2n + 1)/ 6でなければならないことを知っています。
  • 次に、次の連立方程式x + y = S'-S、x²+y²= T'-Tを設定します。
  • X²+y²=(x + y)²-2xy=> xy =((S'-S)²-(T'-T))/ 2と書いて解きます。
  • そして今、数はzの二次方程式の根にすぎません:z²-(S'-S)z +((S'-S)²-(T'-T))/ 2 = 0。

Zを未知数として最終ステップでその2次方程式を設定する理由は何ですか?この問題の解決策であるというその背後にある直感は何ですか?

12
ordinary

この方法はintegerオーバーフローの問題があるため、お勧めできません。したがって、XORメソッドを使用して2つの数値を見つけます。これは、パフォーマンスが高いです。興味があれば説明できます。

以下の @ ordinary からのリクエストに従って、アルゴリズムを説明しています。

[〜#〜]編集[〜#〜]

配列a[]の最大要素がBであると仮定します。つまり、a[]={1,2,4}であり、ここでは35が[]に存在しないため、最大要素はB=5です。

  • xor配列のすべての要素aからX
  • xor1からBからxまでのすべての要素
  • x = x &(~(x-1));によってxの左端のビットセットを見つけます
  • ここで、a[i] ^ x == x than xora[i] to p else xor with q
  • これで、1からkまでのすべてのBについて、k ^ x == xxorよりもpの場合はxorの場合はq
  • 次に、pqを出力します

証明:

a = {1,2,4}およびBが5であるとします。つまり、1から5まで、欠落している数は3と5です。

XORの要素と1から5までの数字をaすると、3と5のXOR、つまりxが残ります。

xの左端のビットセットが見つかった場合、それは3と5の間で左端の最も異なるビットに他なりません(3--> 0115 --> 101、およびx = 010ここでx = 3 ^ 5

この後、xのビットセットに従って2つのグループに分割しようとしているため、2つのグループは次のようになります。

p = 2 , 2 , 3 (all has the 2nd last bit set)

q = 1, 1, 4, 4, 5 (all has the 2nd last bit unset)

XORの要素をpすると、3が見つかります。同様に、xorのすべての要素をqすると、5を取得します。 。したがって、答え。

Javaのコード

public void findNumbers(int[] a, int B){
    int x=0;
    for(int i=0; i<a.length;i++){
        x=x^a[i];
    }
    for(int i=1;i<=B;i++){
        x=x^i;
    }
    x = x &(~(x-1));
    int p=0, q=0;
    for(int i=0;i<a.length;i++){
        if((a[i] & x) == x){
            p=p^a[i];
        }
        else{
            q=q^a[i];
        }   
    }
    for(int i=1;i<=B;i++){
        if((i & x) == x){
            p=p^i;
        }
        else{
            q=q^i;
        }
    }

    System.out.println("p: "+p+" : "+q);
}
25
Trying

Xとyを2次方程式の根とします。

  • 根の合計、SUM = x + y
  • 根の積、PRODUCT = x * y

合計と積がわかっている場合、2次方程式を次のように再構築できます。

z^2 - (SUM)z + (PRODUCT) = 0

あなたが言及したアルゴリズムでは、合計と積を見つけ、そこから、上記の式を使用して二次方程式を再構築します。

詳細な導出に興味がある場合は、 ここにリファレンスがあります「根の和と積からの二次方程式の再構築」を読んでください。

10
slider

上記の問題のアルゴリズムがあります。

仮定します

_Actual Series: 1 2 3 4 5 6          a:sum=21 product= 720
Missing Number series: 1 * 3 4 * 6  b:sum=14 product= 72

a+b=21-14= 7 , ab=720/72=10
_

次に、a-b= sqrt[(a+b)^2 -4ab]を見つける必要があります。

あなたが計算する場合:

_a-b= 3
_

_a+b=7
a-b=3
_

両方の方程式を追加します。

_2a=10, a=5
_

次に_b=7-5=2_なので、_2_と_5_がありません。

5
Manik Gupta

で始まります

x+y == SUM
xy == PRODUCT

2つのケースがあります。 PRODUCTがゼロの場合、一方の数値は0で、もう一方の数値はSUMです。それ以外の場合、両方ともゼロ以外です。等式を変更せずに、最初の方程式にxを掛けることができます。

x*x + xy == x*SUM

2番目の方程式を代入します。

x*x + PRODUCT = x*SUM

通常の形に並べ替えます

x*x - x*SUM + PRODUCT = 0

そのため

x = SUM/2 + sqrt(SUM*SUM - 4*PRODUCT)/2
y = SUM/2 - sqrt(SUM*SUM - 4*PRODUCT)/2
4
Ben Voigt

Java実装:(@ 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;
2
OhadM
Below is the generic answer in Java code for any number of missing numbers in a given array
//assumes that there are no duplicates
a = [1,2,3,4,5]
b = [1,2,5]
a-b=[3,4]

public list<integer> find(int[] input){
  int[] a= new int[] {1,2,3,4,5};//create a new array without missing numbers
  List<Integer> l = new ArrayList<Integer>();//list for missing numbers
  Map<Integer,Integer> m = new HashMap<Integer>();

  //populate a hashmap with the elements in the new array
  for(int i=0;i<input.length;i++){  
   m.put(input[i], 1);
  }
//loop through the given input array and check for missing numbers
 for(int i=0;i<a.length;i++){
  if (!m.contains(input[i]))
   l.add(input[i]);
}
 return l;
}
1
user1789685

欠落している要素の数に関係なく機能します。コードを少しフォーマットできますが、重複および非重複のエントリでも機能します。

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]);
                }

        }


    }
0
Anubha Tripathi

このプログラムが皆さんのお役に立てば幸いです。10まで制限を取りました。同じ方法で実行できます。制限としてnを使用し、同じ操作を実行します。

#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;


}
0
Shivam Sharda
#include <stdio.h>
#include <math.h>

/*
    the sum should be 1+...+n = n(n+1)/2
    the sum of squares should be 1^2+...+n^2 = n(n+1)(2n+1)/6.
*/

void find_missing_2_numbers(int *arr, int n);

int main()
{
    int arr[] = {3,7,1,6,8,5};

    find_missing_2_numbers(arr, 8);

    return 0;
}

void find_missing_2_numbers(int *arr, int n)
{

    int i, size, a, b, sum, sum_of_sqr, a_p_b, as_p_bs, a_i_b, a_m_b;
    size = n - 2;

    sum = 0;
    sum_of_sqr = 0;
    for (i = 0; i < size; i++)
    {
        sum += arr[i];
        sum_of_sqr += (arr[i] * arr[i]);
    }

    a_p_b = (n*(n+1))/2 - sum;
    as_p_bs = (n*(n+1)*(2 * n + 1))/6 - sum_of_sqr;
    a_i_b = ((a_p_b * a_p_b) - as_p_bs ) / 2;
    a_m_b = (int) sqrt((a_p_b * a_p_b) - 4 * a_i_b);
    a = (a_p_b + a_m_b) / 2;
    b = a_p_b - a;

    printf ("A: %d, B: %d\n", a, b);
}
0
Alok Singh