Подтвердить что ты не робот

Как найти пифагорейские триплеты в массиве быстрее, чем O (N ^ 2)?

Может кто-нибудь предложить алгоритм, который находит все пифагорейские триплеты среди чисел в заданном массиве? Если это возможно, предложите алгоритм быстрее, чем O (n 2).

Пифагорейский триплет есть множество {a, b, c} такое, что a 2= b 2 + c 2. Пример: для массива [9, 2, 3, 4, 8, 5, 6, 10] вывод алгоритма должен быть {3, 4, 5} и {6, 8, 10}.

4b9b3361

Ответ 1

Я понимаю этот вопрос как

Для массива найдите все такие триплеты i, j и k, так что a [i] 2= a [j] 2 + а [к] 2

Основная идея решения:

  • Квадрат каждого элемента. (Это занимает время O (n)). Это уменьшит исходную задачу, чтобы "найти три числа в массиве, одна из которых представляет собой сумму двух других".

Теперь вы знаете, как решить такую ​​задачу за меньшее время O (n 2), используйте такой алгоритм. Из моего разума приходит только следующее решение O (n 2):

  • Сортировка массива в порядке возрастания. Это берет O (n log n).
  • Теперь рассмотрим каждый элемент a [i]. Если a [i] = a [j] + a [k], то, поскольку числа положительны и массив теперь отсортирован, k < я и j < i.

    Чтобы найти такие индексы, запустите цикл, который увеличивает j от 1 до i и уменьшает k от i до 0 в то же самое время, пока не встретится. Увеличьте j, если a[j]+a[k] < a[i], и уменьшите k, если сумма больше, чем a[i]. Если сумма равна, то один из ответов, напечатайте ее и сдвиньте оба индекса.

    Это выполняет операции O (i).

  • Повторите шаг 2 для каждого индекса i. Таким образом вам понадобятся полностью операции O (n 2), которые будут окончательной оценкой.

Ответ 2

Никто не знает, как сделать значительно лучше, чем квадратичный для тесно связанной проблемы 3SUM (http://en.wikipedia.org/wiki/3SUM). Я бы оценил возможность быстрого решения вашей проблемы как маловероятного.


Задача 3SUM заключается в нахождении a + b + c = 0. Пусть PYTHTRIP является задачей нахождения a 2 + b ^ 2 = c ^ 2, когда входы являются вещественными алгебраическими числами. Ниже приведено сокращение O (n log n) от 3SUM до PYTHTRIP. Как указывает ShreevatsaR, это не исключает возможности теоретико-числового трюка (или решения для 3SUM!).

Сначала мы уменьшим 3SUM до проблемы, которую я назову 3SUM-ALT. В 3SUM-ALT мы хотим найти a + b = c, где все записи массива неотрицательны. Окончательное сокращение от 3SUM-ALT до PYTHTRIP просто занимает квадратные корни.

Чтобы решить 3SUM с помощью 3SUM-ALT, сначала исключите возможность тройки, где один из a, b, c равен нулю (O (n log n)). Теперь любая удовлетворяющая тройка имеет два положительных числа и один отрицательный или два отрицательных и один положительный. Пусть w - число, большее трехкратное абсолютное значение любого входного числа. Решите два экземпляра 3SUM-ALT: один, где все отрицательные x отображаются в w-x, и все положительные x отображаются на 2w + x; где все отрицательные x отображаются в 2w - x и все положительные x отображаются в w + x. Остальная часть доказательства проста.

Ответ 3

У меня есть еще одно решение,

//sort the array in ascending order 
//find the square of each element in the array

//let 'a' be the array containing square of each element in ascending order 

for(i->0 to (a.length-1))
  for (j->i+1 to  (a.length-1))
    //search the a[i]+a[j] ahead in the array from j+1 to the end of array
      //if found get the triplet according to sqrt(a[i]),sqrt(a[j]) & sqrt(a[i]+a[j])
  endfor
endfor

Ответ 4

Не уверен, что это лучше, но вы можете вычислить их во времени, пропорциональном максимальному значению в списке, просто вычислив все возможные тройки, меньшие или равные ему. Следующий код Perl. Временная сложность алгоритма пропорциональна максимальному значению, так как сумма обратных квадратов 1 + 1/2 ^ 2 + 1/3 ^ 3.... равна Pi ^ 2/6, константа.

Я просто использовал формулу на странице Wikipedia для создания уникальных троек.

my $list = [9, 2, 3, 4, 8, 5, 6, 10];
pythagoreanTriplets ($list);

sub pythagoreanTriplets
{
  my $list = $_[0];
  my %hash;
  my $max = 0;
  foreach my $value (@$list)
  {
    $hash{$value} = 1;
    $max = $value if ($value > $max);
  }
  my $sqrtMax = 1 + int sqrt $max;

  for (my $n = 1; $n <= $sqrtMax; $n++)
  {
    my $n2 = $n * $n;
    for (my $m = $n + 1; $m <= $sqrtMax; $m++)
    {
      my $m2 = $m * $m;
      my $maxK = 1 + int ($max / ($m2 + $n2));
      for (my $k = 1; $k <= $maxK; $k++)
      {
        my $a = $k * ($m2 - $n2);
        my $b = $k * (2 * $m * $n);
        my $c = $k * ($m2 + $n2);
        print "$a $b $c\n" if (exists ($hash{$a}) && exists ($hash{$b}) && exists ($hash{$c}));
      }
    }
  }
}

Ответ 5

Вот решение, которое может масштабироваться лучше для больших списков небольших чисел. По крайней мере, он отличается: v).

Согласно http://en.wikipedia.org/wiki/Pythagorean_triple#Generating_a_triple,

a = m^2 - n^2, b = 2mn, c = m^2 + n^2 

b выглядит хорошо, а??

  • Сортировка массива в O (N log N) времени.
  • Для каждого элемента b найдите простую факторизацию. Наивно используя таблицу простых чисел до квадратного корня из наибольшего входного значения M, вы берете O (sqrt M/log M) время и пространство * на элемент.
  • Для каждой пары (m,n), m > n, b = 2mn (пропустить нечетный b), найдите m^2-n^2 и m^2+n^2 в отсортированном массиве. O (log N) на пару, O (2 ^ (Ω (M))) = O (log M) ** пары на элемент, O (N (log N) (log M)) total.

Окончательный анализ: O (N ((sqrt M/log M) + (log N * log M))), N = размер массива, M = величина значений.

(* Чтобы принять 64-битный ввод, существуют 323-разрядные простые числа 203M, но мы можем использовать таблицу различий в один байт per prime, так как различия все четные и, возможно, также генерируют большие простые числа в последовательности по требованию. Чтобы принять 32-битный ввод, необходима таблица из 16-разрядных простых чисел, которая достаточно мала, чтобы вписаться в кеш L1. Время здесь - это переоценка, предполагающая, что все простые коэффициенты меньше квадратного корня.)

(** Фактическая граница ниже из-за повторяющихся простых факторов.)

Ответ 6

Некоторым из моих сотрудников была задана эта же проблема в учебном курсе java, на котором они принимали решение, с которым мы столкнулись, был O (N ^ 2). Мы сбрили столько проблемного пространства, сколько могли, но мы не смогли найти способ отбросить сложность до N Log N или лучше.

    public static List<int[]> pythagoreanTripplets(int[] input) {
    List<int[]> answers = new ArrayList<int[]>();
    Map<Long, Integer> map = new HashMap<Long, Integer>();

    for (int i = 0; i < input.length; i++) {
        map.put((long)input[i] * (long)input[i], input[i]);
    }

    Long[] unique = (Long[]) map.keySet().toArray(new Long[0]);
    Arrays.sort(unique);
    long comps =0;
    for(int i =  1 ; i < unique.length;i++)
    {
        Long halfC = unique[i]/2;
        for(int j = i-1 ; j>= 0 ; j--)
        {

            if(unique[j] < halfC) break;
            if(map.containsKey(unique[i] - unique[j]))
            {
                answers.add(new int[]{map.get(unique[i] - unique[j]),map.get(unique[j]),map.get(unique[i])});
            }
        }
    }
    return answers;
}

Ответ 7

Решение в O (N).

  • узнать минимальный элемент в массиве. min O (n).
  • узнать максимальный элемент в массиве. max O (n).
  • сделать hastable элементов, чтобы элемент можно было искать в O (1).
  • m ^ 2-1 = min.... положить min из шага 1. найти m в этом уравнении. O (1)
  • 2m = min.... поставьте min из шага 1. найдите m в этом уравнении. O (1)
  • m ^ 2 + 1 = max.... положим max из шага 2. найдите m в этом уравнении. O (1)

  • выберите пол минуты (шаги 4,5,6), скажем, minValue.O(1)

  • выберите ceil max (шаги 4,5,6), скажем maxValue.O(1)

  • цикл от j = minValue до maxValue. maxvalue-minvalue будет меньше, чем корень N. 9. вычислим три числа j ^ 2-1,2j, j ^ 2 + 1. 9.b искать эти цифры в хэш-таблице. если найден возврат успеха.

  • Ошибка возврата.

Ответ 8

Если (a, b, c) является пифагорейской тройкой, то так же (ka, kb, kc) для любого положительного целого.

так что просто найдите одно значение для a, b и c, а затем вы можете вычислить столько новых, сколько хотите.

Псевдокод:

a = 3
b = 4
c = 5
for k in 1..N:
  P[k] = (ka, kb, kc)

Сообщите мне, если это не совсем то, что вы ищете.

Ответ 9

Это тот, который я реализовал...

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * 
 * @author Pranali Choudhari ([email protected])
 */
public class PythagoreanTriple {

/
    //I hope this is optimized



    public static void main(String[] args) {

        Map<Long,Set<Long>> triples = new HashMap<Long,Set<Long>>();
        List<Long> l1 = new ArrayList<Long>();
        addValuesToArrayList(l1);
        long n =0;        
        for(long i : l1){
            //if its side a.
             n = (i-1L)/2L;
             if (n!=0 && n > 0){
                  putInMap(triples,n,i);
                  n=0;
             }
             //if its side b 

             n = ((-1 + Math.round(Math.sqrt(2*i+1)))/2);
             if (n != 0 && n > 0){
                 putInMap(triples,n,i);
                  n=0;
             }
             n=  ((-1 - Math.round(Math.sqrt(2*i+1)))/2);
             if (n != 0 && n > 0){
                 putInMap(triples,n,i);
                  n=0;
             }
             //if its side c

             n = ((-1 + Math.round(Math.sqrt(2*i-1)))/2);
             if (n != 0 && n > 0){
                 putInMap(triples,n,i);
                  n=0;
             }
             n=  ((-1 - Math.round(Math.sqrt(2*i-1)))/2);
             if (n != 0 && n > 0){
                 putInMap(triples,n,i);
                  n=0;
             }


        }
        for(Map.Entry<Long, Set<Long>> e : triples.entrySet()){
            if(e.getValue().size() == 3){
                System.out.println("Tripples" + e.getValue());
            }
            //need to handle scenario when size() > 3 
            //even those are tripples but we need to filter the wrong ones
        }


    }

    private static void putInMap( Map<Long,Set<Long>> triples, long n,  Long i) {
        Set<Long> set = triples.get(n);
        if(set == null){
            set = new HashSet<Long>();
            triples.put(n, set);
        }
        set.add(i);
    }

    //add values here 
    private static void addValuesToArrayList(List<Long> l1) {
        l1.add(1L);
        l1.add(2L);
        l1.add(3L);
        l1.add(4L);
        l1.add(5L);
        l1.add(12L);
        l1.add(13L);

    }
}

Ответ 10

Это можно сделать в O (n) времени. сначала хэш-элементы на карте для проверки существования. после этого примените приведенный ниже алгоритм

Сканирование массива, и если элемент является четным числом, (n, n ^ 2/2 +1, n ^ 2/2 -1) является тройкой, которую можно найти. просто проверьте это существование с помощью поиска хэш-карт. если все элементы в триплете существуют, напечатайте триплет.

Ответ 11

Здесь реализация в Java:

/**
 * Step1: Square each of the elements in the array [O(n)]
 * Step2: Sort the array [O(n logn)]
 * Step3: For each element in the array, find all the pairs in the array whose sum is equal to that element [O(n2)]
 * 
 * Time Complexity: O(n2) 
 */
public static Set<Set<Integer>> findAllPythogoreanTriplets(int [] unsortedData) {

    // O(n) - Square all the elements in the array
    for (int i = 0; i < unsortedData.length; i++)
        unsortedData[i] *= unsortedData[i];

    // O(n logn) - Sort
    int [] sortedSquareData = QuickSort.sort(unsortedData);

    // O(n2)
    Set<Set<Integer>> triplets = new HashSet<Set<Integer>>();

    for (int i = 0; i < sortedSquareData.length; i++) {

        Set<Set<Integer>> pairs = findAllPairsThatSumToAConstant(sortedSquareData, sortedSquareData[i]);

        for (Set<Integer> pair : pairs) {
            Set<Integer> triplet = new HashSet<Integer>();
            for (Integer n : pair) {
                triplet.add((int)Math.sqrt(n));
            }
            triplet.add((int)Math.sqrt(sortedSquareData[i])); // adding the third element to the pair to make it a triplet
            triplets.add(triplet);
        }
    }

    return triplets;
}


public static Set<Set<Integer>> findAllPairsThatSumToAConstant(int [] sortedData, int constant) {

    // O(n)
    Set<Set<Integer>> pairs = new HashSet<Set<Integer>>();
    int p1 = 0; // pointing to the first element
    int p2 = sortedData.length - 1; // pointing to the last element
    while (p1 < p2) {
        int pointersSum = sortedData[p1] + sortedData[p2];
        if (pointersSum > constant)
            p2--;
        else if (pointersSum < constant)
            p1++;
        else {
            Set<Integer> set = new HashSet<Integer>();
            set.add(sortedData[p1]);
            set.add(sortedData[p2]);
            pairs.add(set);
            p1++;
            p2--;
        }
    }
    return pairs;
}

Ответ 12

если проблема такова: "Для массива целых чисел найдутся все тройки такие, что a ^ 2 + b ^ 2 = c ^ 2

Сортировка массива в порядке возрастания

Установите три указателя p1, p2, p3 на позиции 0,1,2 установите pEnd на последнюю запись в массиве

while (p2 < pend-2) {

sum = (*p1 * *p1 + *p2 * *p2)


while ((*p3 * *p3) < sum && p3 < pEnd -1)
   p3++;

if ( *p3 == sum) 
   output_triple(*p1, *p2, *p3);

p1++;
p2++;

}

он перемещает 3 указателя на массив, так что O (sort (n) + n) это не n2, потому что следующий проход начинается с следующего наибольшего числа и не reset. если последнее число было слишком маленьким для тройки, оно все еще мало, когда вы переходите к следующим большим a и b

Ответ 13

public class FindPythagorusCombination {

    public static void main(String[] args) {
        int[] no={1, 5, 3, 4, 8, 10, 6 };
        int[] sortedno= sorno(no);
        findPythaComb(sortedno);
    }

    private static void findPythaComb(int[] sortedno) {
        for(int i=0; i<sortedno.length;i++){

            int lSum=0, rSum=0;
            lSum= sortedno[i]*sortedno[i];
            for(int j=i+1; j<sortedno.length; j++){
                for(int k=j+1; k<sortedno.length;k++){
                    rSum= (sortedno[j]*sortedno[j])+(sortedno[k]*sortedno[k]);
                    if(lSum==rSum){
                        System.out.println("Pythagorus combination found: " +sortedno[i] +" " +sortedno[j]+" "+sortedno[k]);
                    }else
                        rSum=0;
                }

            }
        }
    }

    private static int[] sorno(int[] no) {

        for(int i=0; i<no.length;i++){

            for(int j=i+1; j<no.length;j++){
                if(no[i]<no[j]){
                    int temp= no[i];
                    no[i]= no[j];
                    no[j]=temp;
                }
            }

        }

        return no;

    }



}

Ответ 14

    import java.io.*;
import java.lang.*;
import java.util.*;

class PythagoreanTriplets
{
 public static void main(String args[])throws IOException
 {
  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

  int n = Integer.parseInt(br.readLine());
  int arr[] = new int[n];
  int i,j,k,sum;
  System.out.println("Enter the numbers ");
  for(i=0;i<n;i++)
   {
    arr[i]=Integer.parseInt(br.readLine());
    arr[i]=arr[i]*arr[i];
   }
Arrays.sort(arr);
  for(i=n-1;i>=0;i--)
   {
     for(j=0,k=i-1;j<k;)
        {  
          sum=arr[j]+arr[k];
          if(sum==arr[i]){System.out.println((int)Math.sqrt(arr[i]) +","+(int)Math.sqrt(arr[j])+","+(int)Math.sqrt(arr[k]));break;}
          else if(sum>arr[i])k--;
          else j++;

        }
   }

}
}

Ответ 15

Поиск пифагорейских триплетов в O (n)

Алгоритм:

  • Для каждого элемента массива проверьте его простое или нет
  • если он является простым, вычислить другие два числа как ((n ^ 2) +1)/2 и ((n ^ 2) -1)/2 и проверить, находятся ли эти два рассчитанных числа в массиве
  • если он не является простым, вычислите другие два числа, как указано в другом случае в коде, приведенном ниже
  • Повторяйте до достижения конца массива

     int arr[]={1,2,3,4,5,6,7,8,9,10,12,13,11,60,61};
     int prim[]={3,5,7,11};//store all the prime numbers
     int r,l;
     List<Integer> prime=new ArrayList<Integer>();//storing in list,so that it is easy to search
     for(int i=0;i<4;i++){
      prime.add(prim[i]);
     }
     List<Integer> n=new ArrayList<Integer>();
     for(int i=0;i<arr.length;i++)
     {
            n.add(arr[i]);
     }
     double v1,v2,v3;
     int dummy[]=new int[arr.length];
     for(int i=0;i<arr.length;i++)
        dummy[i]=arr[i];
    
     Integer x=0,y=0,z=0;
     List<Integer> temp=new ArrayList<Integer>();
     for(int i=0;i<arr.length;i++)
     {
         temp.add(arr[i]);
     }
    
     for(int j:n){
        if(prime.contains(j)){//if it is prime
            double a,b; 
            v1=(double)j;
            v2=Math.ceil(((j*j)+1)/2);
            v3=Math.ceil(((j*j)-1)/2);
            if(n.contains((int)v2) && n.contains((int)v3)){
              System.out.println((int)v1+" "+(int)v2+" "+(int)v3);
            }
        }
        else//if it is not prime
        {
             if(j%3==0){
                x=j;
                y=4*(j/3);
                z=5*(j/3);
                if(temp.contains(y) && temp.contains(z)){
                        System.out.println(x+" "+y+" "+z);
                        //replacing those three elements with 0
                        dummy[temp.indexOf(x)-1]=0;
                        dummy[temp.indexOf(y)-1]=0;
                        dummy[temp.indexOf(z)-1]=0;
                }
             }   
        }//else end
    }//for end
    

Сложность: O (n)