BST из двух несортированных массивов - PullRequest
8 голосов
/ 22 марта 2012

Этот вопрос был задан в одном из интервью: Учитывая два несортированных массива, проверьте, создаст ли он тот же самый bst. например: 2, 1, 4, 0 и 2, 1, 0, 4 оба будут образовывать один и тот же BST.

     2
    / \
   1   4
  /
 0

Пожалуйста, предложите хороший алгоритм.

Ответы [ 7 ]

4 голосов
/ 22 марта 2012
  • Возьмите первый элемент - это будет корень (в приведенном выше случае это 2)
  • Все элементы, которые меньше корневого элемента, должны отображаться в одном и том же порядке в обоихмассивы
    • В приведенном выше примере 0 и 1 являются элементами, меньшими, чем корневые элементы.
    • В первом массиве порядок равен 1, 0
    • Такой же порядок поддерживается во втором массиве.Таким образом, оба формируют одну и ту же структуру
  • Все элементы, превышающие корневой элемент, должны появляться в одном и том же порядке в обоих массивах

    • В приведенном выше примере 4 является единственным элементом больше 2. Он появляется в обоих массивах.И поэтому оба массива создают BST, которые структурно одинаковы.
  • И, конечно, самое первое условие состоит в том, что оба массива должны содержать одинаковые элементы, но в разном порядке.

Следовательно, это можно решить за линейное время.

Псевдокод будет выглядеть так:

int GetNextIncresingElement(int[] arr, ref int index, int root)
{
    for(int i = index; i< arr.Length; i++)
    {
        if(arr[i] > root)
        {
            index = i;
            return arr[i];
        }
    }
    return -1;
}

int GetNextDecreasingElement(int[] arr, ref int index, int root)
{
    for(int i = index; i< arr.Length; i++)
    {
        if(arr[i] <= root)
        {
            index = i;
            return arr[i];
        }
    }
    return -1;
}

bool CheckFormsSameBST(int[] arr1, int[] arr2)
{
    int index1 = 1;
    int index2 = 1;
    int num1;
    int num2;

    int root = arr1[0];
    if(root != arr2[0])
        return false;

    while(true)
    {
        num1 = GetNextIncresingElement(arr1, ref index1, root);
        num2 = GetNextIncresingElement(arr2, ref index2, root);     

        if(num1 != num2)
            return false;       
        else
        {
            if(num1 == -1)
                break;
        }   

        index1++;
        index2++;
    }

    index1 = 1;
    index2 = 1;
    while(true)
    {
        num1 = GetNextDecreasingElement(arr1, ref index1, root);
        num2 = GetNextDecreasingElement(arr2, ref index2, root);        

        if(num1 != num2)
            return false;       
        else
        {
            if(num1 == -1)
                break;
        }   

        index1++;
        index2++;
    }

    return true;
}
1 голос
/ 22 марта 2012

Я согласен с идеей, описанной Петром и Алгористом.Но я полагаю, что поддеревья каждого узла (представленного массивом, меньшим, чем этот узел, и массивом, большим, чем он) также должны быть изучены таким же образом.Например, 621407 и 621047 дают один и тот же BST, а 624017 - нет.Функция может быть написана рекурсивно.

добавлен пример кода:

bool sameBST(int * t1, int * t2, int startPos, int endPos) {
    int rootPos1, rootPos2;
    if (endPos-startPos<0) return true;
    if (t1[startPos]!=t2[startPos]) return false;
    rootPos1=partition(t1,startPos,endPos,t1[startPos]);
    rootPos2=partition(t2,startPos,endPos,t2[startPos]);
    if (rootPos1!=rootPos2) return false;
    return sameBST(t1,t2,startPos,rootPos1-1) && sameBST(t1,t2,rootPos1+1,endPos);
}

Функциональный раздел - тот же, который вы используете в быстрой сортировке.По-видимому, T (n) = 2T (n / 2) + O (n), что приводит к временной сложности T (n) = O (nlogn).Из-за рекурсии сложность пространства равна O (logn)

0 голосов
/ 23 июля 2016

1) Сортировка массива с использованием подсчета или сортировки по основанию.

2) Построить дерево, используя наш отсортированный массив и заданный несортированный массив (для проверки порядка вставки). Это сохранит структуру дерева.

3) Сравните оба дерева.

Все можно сделать за линейное время - O (n).

Код:

import java.util.Arrays;
public class BSTFromUnsorted {

static class Node{
    int key;
    int arrivalTime,min,max,root;
    Node left;
    Node right;
    Node(int k,int at){
        key=k;left=null;right=null;arrivalTime=at;
    }
}
public static void printTree(Node n){
    if(n==null) return;
    System.out.println(n.key+" "+ ((n.left!=null)?n.left.key:"-") + " " + ((n.right!=null)?n.right.key:"-") );
    printTree(n.left);
    printTree(n.right);
}
public static boolean compareTree(Node n1,Node n2){
    if(n1==null && n2==null) return true;
    return ( n1!=null && n2!=null && n1.key==n2.key && compareTree(n1.left,n2.left) && compareTree(n1.right,n2.right) ) ;
}
public static void main(String[] args){
    int[] bstInsertOrder1={8, 10, 14, 3, 6, 4, 1, 7, 13};
    int[] bstInsertOrder2={8, 3, 6, 1, 4, 7, 10, 14, 13};
    Node n1 = buildBST(bstInsertOrder1);
    printTree(n1);
    System.out.println();
    Node n2 = buildBST(bstInsertOrder2);
    printTree(n2);
    System.out.println("\nBoth are " + (compareTree(n1,n2)?"same":"different"));
}
public static Node buildBST(int[] insertOrder){
    int length = insertOrder.length;
    Node[] sortedOrder = new Node[length];
    for(int i=0;i<length;i++){
        sortedOrder[i] = new Node(insertOrder[i],i);
    }
    Radix.radixsort(sortedOrder,length);
    int[] sortedIndex = new int[length];
    for(int i=0;i<length;i++){
        sortedOrder[i].max=sortedOrder[i].min=sortedOrder[i].root=i;
        sortedIndex[sortedOrder[i].arrivalTime]=i;
    }
    for (int i=length-1;i>0;i--){
        int j = sortedIndex[i];
        int min=sortedOrder[j].min-1,max=sortedOrder[j].max+1;
        Node n=null,n1;
        if(min>=0){
            n = sortedOrder[sortedOrder[min].root];
        }
        if(max<length){
            n1=sortedOrder[sortedOrder[max].root];
            if(n==null){
                n=n1;
            }
            else{
                n=(n.arrivalTime>n1.arrivalTime)?n:n1;
            }
        }
        n1=sortedOrder[j];
        if(n.key<n1.key){
            n.right=n1;
            n.max=n1.max;
            sortedOrder[n.max].root=sortedOrder[n.min].root;
        }
        else{
            n.left=n1;
            n.min=n1.min;
            sortedOrder[n.min].root=sortedOrder[n.max].root;
        }
    }
    return sortedOrder[sortedIndex[0]];
}
static class Radix {
    static int getMax(Node[] arr, int n) {
        int mx = arr[0].key;
        for (int i = 1; i < n; i++)
            if (arr[i].key > mx)
                mx = arr[i].key;
        return mx;
    }
    static void countSort(Node[] arr, int n, int exp) {
        Node output[] = new Node[n]; // output array
        int i;
        int count[] = new int[10];
        Arrays.fill(count, 0);
        for (i = 0; i < n; i++)
            count[(arr[i].key / exp) % 10]++;
        for (i = 1; i < 10; i++)
            count[i] += count[i - 1];
        for (i = n - 1; i >= 0; i--) {
            output[count[(arr[i].key / exp) % 10] - 1] = arr[i];
            count[(arr[i].key / exp) % 10]--;
        }
        for (i = 0; i < n; i++)
            arr[i] = output[i];
    }
    static void radixsort(Node[] arr, int n) {
        int m = getMax(arr, n);
        for (int exp = 1; m / exp > 0; exp *= 10)
            countSort(arr, n, exp);
    }
}

}
0 голосов
/ 23 марта 2012

Смысл может состоять в том, чтобы сравнивать перестановки подсегментов одного массива с соответствующими подсегментами другого массива (порядок уровней мышления):

начиная с первого элемента в массиве, от i = 0 до некоторого n, сгруппировать элементы в наборы из 2 ^ i

2 ^ 0 = 1: первый элемент является корневым - должны начинаться оба массива: [50].

2 ^ 1 = 2: любая перестановка следующих 2 элементов в порядке:

[25,75] or [75,25]

2 ^ 2 = 4: любая перестановка следующих 4 элементов в порядке:

[10, 35, 60, 85] or [60, 35, 10, 85] or ...

2 ^ 3 = 8: любая перестановка следующих 8 элементов в порядке:

 [5, 16, 30, 40, ….

так до 2 ^ n, пока массивы не станут пустыми. соответствующие подсегменты должны иметь одинаковое количество элементов.

0 голосов
/ 22 марта 2012

проверить, будет ли он создавать тот же bst?

Да.

начните принимать первый элемент как корень и сохраняйте число, которое больше, чем корень справа, и меньше, чем корень слева.

если вы выполните описанную выше процедуру, вы увидите, что оба дерева идентичны.

0 голосов
/ 22 марта 2012

IMO, вы можете отсортировать один массив и выполнить бинарный поиск из второго массива в отсортированный массив, при этом убедитесь, что вы используете каждый элемент. Это обойдется вам в миллион.

0 голосов
/ 22 марта 2012

Вы можете проверить подробное объяснение, сравнивая два двоичных дерева (не только BST) в Определите, равны ли два двоичных дерева . Легко создать BST из массивов, а затем запустить алгоритм в упомянутых вопросах.

...