Bu bir BST ön sipariş geçişi midir?


21

Arka fon

Bir ikili ağaç olan her düğüm en fazla iki çocukları olan bir köklü bir ağaçtır.

Bir etiketlenmiş ikili ağaç olan her bir düğüm bir pozitif tamsayı ile işaretlenmiş olan bir ikili ağaç olduğu; dahası, tüm etiketler belirgindir .

Bir BST (ikili arama ağacı), her bir düğümün etiketinin sol alt ağacındaki tüm düğümlerin etiketlerinden daha büyük ve sağ alt ağacındaki tüm düğümlerin etiketlerinden daha küçük olduğu etiketli bir ikili ağaçtır. Örneğin, aşağıdakiler bir BST'dir:

Bir BST

Ön sipariş geçişi etiketlenmiş bir ikili ağacın aşağıdaki yalancı kod ile tanımlanır.

function preorder(node)
    if node is null then
        return
    else
        print(node.label)
        preorder(node.left)
        preorder(node.right)

Daha iyi bir sezgi elde etmek için aşağıdaki resme bakın:

BT ön sipariş geçişi

Bu ikili ağacın köşeleri aşağıdaki sırayla yazdırılır:

F, B, A, D, C, E, G, I, H

Burada BST'ler ve burada ön sipariş geçişi hakkında daha fazla bilgi edinebilirsiniz .

Meydan okuma

Sayının bir liste Verilen a , görev kimin tam olarak ön sipariş geçişi baskılar bir BST olup olmadığını belirlemektir a .

Giriş

  • Boş olmayan bir tam pozitif tamsayı listesi a .
  • İsteğe bağlı olarak, a .

Çıktı

  • Bir truthy değeri ise a bazı BST ön sipariş geçişi olan.
  • Aksi takdirde bir falsey değeri.

kurallar

  • Geçerli gönderimler için standart kurallar , G / Ç , boşluklar geçerlidir.
  • Bu , yani en kısa çözüm (bayt cinsinden) kazanır. Her zamanki gibi, golfçü dillerde saçma sapan kısa çözümlerin, seçtiğiniz dilde daha uzun bir cevap göndermekten vazgeçmesine izin vermeyin.
  • Bu bir kural değildir, ancak çözümü test etmek için bir bağlantı ve nasıl çalıştığı hakkında bir açıklama içeriyorsa, cevabınız daha iyi alınacaktır.

Örnekler

Input                   ---->   Output

[1]                     ---->   True
[1,2,3,4]               ---->   True
[5,1,4,2,3]             ---->   True
[5,4,3,2,1,6,7,8,9]     ---->   True
[4,2,1,3,6,5,7]         ---->   True
[8,3,1,6,4,7,10,14,13]  ---->   True
[2,3,1]                 ---->   False
[6,3,2,4,5,1,8,7,9]     ---->   False
[1,2,3,4,5,7,8,6]       ---->   False
[3,1,4,2]               ---->   False

Check out bu bağlantıyı (nezaket Kevin Cruijssen örneklere dair görsel bir bakış var).



Tüm tamsayıların pozitif olduğunu varsayabilir miyiz?
GB

@GB Evet. Yayını şimdi düzenleyeceğim.
Delfad0r

Yanıtlar:


11

JavaScript (Node.js) , 49 bayt

a=>!a.some((p,i)=>a.some((q,j)=>q>p&a[j+=j>i]<p))

Çevrimiçi deneyin!

a0...an1a0i<j<n;ai<aj1ai<aj

Arnauld sayesinde 1 byte tasarruf edin.


8

Jöle , 7 bayt

ŒPŒ¿€4ḟ

Çevrimiçi deneyin!

İade [4]aksi geçişleri için, [].

Esasen TSH hormonunun algoritma kullanır: Bir ön sipariş geçişi için "disqualifying" koşulu bir olan dizinin bundan 3 elemanlarının böyle görünüyor [orta, yüksek, düşük] . (Örneğin, [20, 30, 10].)

Değişkenlik listelerinde indeks 4'ü olan herhangi bir uzunluktaki tüm alt dizileri eşdeğerde kontrol ederiz , ki bunlar [a 1 … a k cdb] şeklinde sıralanmıştır. nerede bir i sıralanır ve bir i <b <c <d . (Bu üç liste son üç öğeye bakarsak diskalifiye eder ve her diskalifiye listesi açıkça bu biçimdedir.)

ŒP          All subsequences.
  Œ¿€       Permutation index of each.
     4ḟ     Set difference of {4} and this list.

Kanıt

Ön sipariş geçme işlemi diskalifiye edici alt diziler içermiyor

Temel durum: geçiş (•) boş listedir. ✓

İndüksiyon: geçiş (t) : t.root ++ çaprazlama (t.left) ++ çaprazlama (t.right) .

let [a, b, c] bunun bir alt-dizisinin olabilir. İmkansız olduğunu c <a <b olarak göstereceğiz .

  • Eğer t.root = a ise , c <a <b c ∈ t.left gerektirir ve b ∈ t.right , yani [c, b,] yanlış sırasıdır.
  • Eğer a, b, c ∈ t.left veya a, b, c ∈ t.right , indüksiyon hipotezi kullanabilir.
  • Bir yarık ve sağ c t.se, o zaman c> a .

Ekleri diskalifiye etmeden farklı tam sayıların listesi, bir BST'nin ön-sıra geçişidir.

Liste boşsa, önemsiz BST'nin • geçişidir.

Eğer liste başı takip ederse kuyruk :

  • Let az en uzun önek olmak kuyruk daha az elementlerin kafası ve izin daha listenin geri kalanında.
  • O zaman daha fazla [1]> kafa ve diğer tüm [i] de kafadan büyüktür (aksi halde [kafa, daha fazla [1], daha fazla [i]] diskalifiye edici bir sonuç olur).
  • Tekrarlama : daha az ve daha fazlasını BST'lere çevirin.
  • Şimdi listemiz geçişi

                     head
                    /    \
             BST(less)   BST(more),
    

    ve bu ağaç geçerli bir BST'dir.


1
Güzel kanıt. Aslında cevabı gönderdiğimde formülü ispat etmedim. BST'yi girişten inşa etmeye çalıştıktan sonra bunun doğru olduğunu hissettim.
tsh

5

Java 10, 94 bayt

a->{var r=0>1;for(int j=a.length-1,i;j-->0;)for(i=0;i<j;)r|=a[j]>a[i]&a[j+1]<a[i++];return!r;}

Port @tsh 'JavaScript cevap .

Çevrimiçi deneyin.

Açıklama:

a->{                      // Method with integer-array parameter and boolean return-type
  var r=0>1;              //  Result-boolean, starting at false
  for(int j=a.length-1,i;j-->0;)
                          //  Loop `j` in the range (length-1, 0]:
    for(i=0;i<j;)         //   Inner loop `i` in the range [0, j):
      r|=                 //    If any are true, change the result to true as well:
         a[j]>a[i]        //     The `j`'th item is larger than the `i`'th item
         &a[j+1]<a[i++];  //     And the `j+1`'th item is smaller than the `i`'th item
  return!r;}              //  After the nested loop, check if the boolean is still false

1
Java boolean'leri ile yeniden atanabilir |=. Sanırım &=işe yarayacak mı?
J. Sallé

@ J.Sallé Evet, hem |=ve &=kısayollar olarak çalışma b = b | conditionve b = b & condition(nerede &ve |için kısayollarıdır &&ve ||tabii ki birçok durumda).
Kevin Cruijssen

5

Ruby , 46 40 38 bayt

f=->r{a,*b=r;!a||b==b&[*0..a]|b&&f[b]}

Çevrimiçi deneyin!

Bu, ilk öğeyi yinelemeli aolarak bir pivot olarak alarak ve dizinin geri kalanının ikiye bölünüp bölünmeyeceğini denetleyerek çalışır (kesişim ve birliği kullanarak: önce tüm öğeleri kaldır> a, sonra tekrar sağa ekleyin ve bir şey olup olmadığını kontrol edin değişti).


3

Retina 0.8.2 , 31 bayt

\d+
$*
M`\b((1+)1+,).*\1\2\b
^0

Çevrimiçi deneyin! Link, test durumlarını içerir. @ Tsh'nin algoritmasını kullanır. Açıklama:

\d+
$*

Birliğe dönüştür.

M`\b((1+)1+,).*\1\2\b

Ardışık iki azalan sayı arasında kalan sayıları bulun.

^0

Eşleşme sayısının sıfır olduğunu kontrol edin.


3

Perl 6 , 38 bayt

!*.combinations(3).grep:{[>] .[1,0,2]}

Çevrimiçi deneyin!

açıklama

 *.combinations(3)  # All combinations of 3 elements a,b,c
!                 .grep:{            }  # Return false if check succeeds for any combination
                         [>] .[1,0,2]   # Check whether b>a>c, that is b>a and c<a


3

Scala ( 68 67 Bayt)

def%(i:Seq[Int])= !i.combinations(3).exists(c=>c(0)<c(1)&c(0)>c(2))

Çevrimiçi deneyin

@ Nwellnhof kullanıcısının yanıtı .

Scala ( 122 103 bayt)

def f(i:Seq[Int]):Boolean=if(i.size<1)1>0 else{val(s,t)=i.tail.span(_<i(0));t.forall(_>i(0))&f(s)&f(t)}

Her iki çözümü de kısaltma önerileri için @Likonikon'a teşekkürler.

Çevrimiçi deneyin

Açıklama:

  1. spanDilimleme (Scala kullanarak ) dilimleme kriteri olarak dizenin başını kullanarak diziyi.
  2. Dizinin ilk diliminin kafadan daha az ve ikinci dilimin kafadan daha büyük olduğunu onaylayın.
  3. tekrarlayarak her bir dilimin de yerine getirildiğini kontrol edin (2)

1
İçindeki boşluğa ihtiyacınız olmadığını düşünüyorum val (s,t), trueolabilir 1>0ve s.forall(_<i(0))&bunun zaten sigortalı olması gerektiği gibi düşebilirsiniz span.
Laikoni

1
Fonksiyonu çağırabilir %ve alanı bırakabilirsiniz:def%(i:Seq[Int])=
Laikoni

Çözümleriniz, diğerlerinden farklı olarak işlev bildirimini içerir. Saf ifadeler oldukça kısa. ;)
Dr Y Wit,

Tsh'nin cevabını taşımaya çalışıyordum, ama yeterince kısa sürmeyi beceremedi. Sürüm 1 l.zipWithIndex.foldLeft(1>0){case(r,v,i)=>r&l.zip(l.tail).slice(i+1,l.length).forall(x=>l(i)>x._1|l(i)<x._2)}. Sürüm 2 (for(i<-l.indices)yield l.zip(l.tail).slice(i+1,l.length).forall(x =>l(i)>x._1|l(i)<x._2)).forall(x=>x). Bunları kısaltmak için herhangi bir fikir?
Dr Y Wit,

Düz İngilizce olarak Algoritma: Her bir eleman için yan yana tüm eleman çiftlerini kontrol edin.
Dr Y Wit,

2

05AB1E , 15 10 bayt

ŒεD{3.IÊ}P

Port @Lynn 'in Jelly cevap . @Emigna
sayesinde -5 bayt .

Çevrimiçi deneyin veya tüm test durumlarını doğrulayın .

Açıklama: "

Œ             # Take all sublists of the (implicit) input-list
              #  i.e. [2,3,1] → [[2],[2,3],[2,3,1],[3],[3,1],[1]]
              #  i.e. [1,2,3,4]
              #   → [[1],[1,2],[1,2,3],[1,2,3,4],[2],[2,3],[2,3,4],[3],[3,4],[4]]
 ε      }     # Map each to:
  D           #  Duplicate the current sublist on the stack
   {          #  Sort the copy
              #   i.e. [2,3,1] → [1,2,3]
              #   i.e. [2,3,4] → [2,3,4]
    3.I       #  Get the 4th (3rd 0-indexed) permutation of this list
              #   i.e. [1,2,3] → [2,3,1]
              #   i.e. [2,3,4] → [3,4,2]
       Ê      #  Check that the lists are NOT equal
              #   i.e. [2,3,1] and [2,3,1] → 0 (falsey)
              #   i.e. [2,3,4] and [3,4,2] → 1 (truthy)
         P    # Check whether all are truthy (and output implicitly)
              #  i.e. [1,1,0,1,1,1] → 0 (falsey)
              #  i.e. [1,1,1,1,1,1,1,1,1,1] → 1 (truthy)

1
Ne dersiniz ŒεD{3.IÊ}P?
Emigna

1
@Emigna Evet, bu gerçekten çok daha kolay olurdu ...>.> Teşekkürler! :) (Ve güzel bir hafta sonu
geçir

2

Haskell , 41 bayt

f(h:t)=t==[]||all(>h)(snd$span(<h)t)&&f t

Çevrimiçi deneyin!

Lynn'in , orta-yüksek ... düşük ... için bir sonuç olmadığını kontrol etmenin yeterli olduğuna dair gözlemini kullanır . Bunun anlamı, her eleman için h, tsonra gelen elemanların listesinin, bir eleman bloğu <htarafından takip edilen bir eleman bloğu olduğu anlamına gelir >h(her iki blok da boş olabilir). Biz elemanların önek bıraktıktan sonra Yani, kod denetler o <hiçinde tkalan elemanlar hepsi>h . Özyineleme h, liste uzunluğu 1 olana kadar her ilk öğe için bunu kontrol eder .

Potansiyel bir sadeleştirme, son iki ardışık olan orta yükseklikte alt kalıpları kontrol etmek için yeterli olmasıdır . Maalesef, Haskell'in, son iki elementi çıkarmak için kısa bir yolu yoktur, zira önden bir desen eşleşmesiyle yapılabilir a:b:c. Orta, yüksek ... düşük kontroller için daha kısa bir çözüm buldum , ancak bu gibi girişleri reddetmiyor [3,1,4,2].

Laikoni'den alınmış formatlı test çalışmaları .


1

Japt , 14 bayt

d@sY ð_§XÃxÈ-Y

Japt Tercüman

falseBST çıkışları , BST trueyok.

Açıklama:

d@                Run on each item X, return true if any aren't 0: 
  sY                  Ignore the numbers before this index
     ð_§XÃ            Get the indexes of numbers less than or equal to X
                          If it is a BST, this list will be e.g. [0,1,2...]
            -Y        Subtract the position within the index list from each index
                          eg. [0,1,2] -> [0,0,0] , [0,1,4] -> [0,0,2]
          xÈ          Sum the resulting array

1

Scala

Tüm yaklaşımlar tsh tarafından gösterilen kuralın uygulamalarıdır.

109

l.zipWithIndex.foldLeft(1>0){case(r,(v,i))=>r&l.zip(l.tail).slice(i+1,l.size).forall(x=>l(i)>x._1|l(i)<x._2)}

101

(for(i<-l.indices)yield l.zip(l.tail).slice(i+1,l.size).forall(x =>l(i)>x._1|l(i)<x._2)).forall(x=>x)

98

l.indices.foldLeft(1>0)((r,i)=>r&(l.zip(l.tail).slice(i+1,l.size).forall(x=>l(i)>x._1|l(i)<x._2)))

78

(for(i<-l.indices;j<-i+1 to l.size-2)yield l(i)>l(j)|l(i)<l(j+1)).forall(x=>x)

Sadece bir ifade değil, bir fonksiyon olması gerekiyorsa, her satırın (17 bayt) ile başlaması gerekir.

def%(l:Seq[Int])=

0

Oracle SQL, 177 bayt

with r(i,v)as(select rownum,value(t)from table(a)t)
select nvl(min(case when r.v<p.l and r.v>p.v then 0end),1)from r,(select i,lag(v)over(order by i)l,v from r)p where r.i+1<p.i

Oracle SQL'de bir boolean türü olmadığından, sorgu 1 veya 0 döndürür.

Oracle SQL 12c, 210 bayt

with function f(n ku$_objnumset,i int)return int as begin return n(i);end;
select min(case when f(c,1)>f(c,2)or f(c,1)<f(c,3)then 1else 0end)from(select value(t)c from table(powermultiset_by_cardinality(a,3))t)

Dizideki erişim elemanının SQL'deki PL / SQL ile aynı şekilde olması mümkün değildir - yani a (i), böylece işlev fbildirildiwith clause bu amaçla . Aksi takdirde, çözüm çok daha kısa olurdu.

Diğer kısıtlamalar

  • 3 öğeden kısa diziler için bir istisna atar (1 yerine)
  • belgelerde açıkça belirtilmediği halde powermultiset_by_cardinality'nin düzeni koruduğu varsayımı var

sqlplus listesi

SQL> set heading off
SQL> with r(i,v)as(select rownum,value(t)from table(ku$_objnumset(6,3,2,4,5,1,8,7,9))t)
  2  select nvl(min(case when r.v<p.l and r.v>p.v then 0end),1)from r,
  3  (select i,lag(v)over(order by i)l,v from r)p where r.i+1<p.i
  4  /

                                            0

SQL> with function f(n ku$_objnumset,i int)return int as begin return n(i);end;
  2  select min(case when f(c,1)>f(c,2)or f(c,1)<f(c,3)then 1else 0end)
  3  from(select value(t)c from table(powermultiset_by_cardinality(ku$_objnumset(6,3,2,4,5,1,8,7,9),3))t)
  4  /

                                                     0

SQL> with r(i,v)as(select rownum,value(t)from table(ku$_objnumset(8,3,1,6,4,7,10,14,13))t)
  2  select nvl(min(case when r.v<p.l and r.v>p.v then 0end),1)from r,
  3  (select i,lag(v)over(order by i)l,v from r)p where r.i+1<p.i
  4  /

                                            1

SQL> with function f(n ku$_objnumset,i int)return int as begin return n(i);end;
  2  select min(case when f(c,1)>f(c,2)or f(c,1)<f(c,3)then 1else 0end)
  3  from(select value(t)c from table(powermultiset_by_cardinality(ku$_objnumset(8,3,1,6,4,7,10,14,13),3))t)
  4  /

                                                     1

Çevrimiçi doğrulama apex.oracle.com

Güncelleştirme

Oracle SQL, 155 bayt

with r(i,v)as(select rownum,value(t)from table(a)t)select nvl(min(case when a.v<b.v and a.v>c.v then 0end),1)r from r a,r b,r c where a.i<b.i and b.i+1=c.i

0

C, 823 bayt (boşluk karakterlerini saymaz); 923 bayt (boşluk dahil)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tree
{struct tree * left;struct tree * right;int val;}tree;static int * test_p = 0;
void insert_root(tree ** root, int in)
{if (*root == NULL){*root = (tree *)calloc(1,sizeof(tree));(*root)->val = in;return;}else if (in < (*root)->val){insert_root(&((*root)->left),in);}else{insert_root(&((*root)->right),in);}}
void preorder(tree * root)
{if ( root == 0x0 ) { return; }*test_p++ = root->val;preorder(root->left);preorder(root->right);}
int main(int argc, char ** argv)
{int test_list[argc-1];memset(test_list,0,argc*sizeof(int));test_p = test_list;tree * root = (tree *)calloc(1,sizeof(tree));root->val = strtol(argv[1],0x0,10);int i = 1;while ( argv[++i] != 0x0 ){insert_root(&root,strtol(argv[i],0x0,10));}preorder(root);test_p = test_list;i = 1;while ( ( i < argc ) ){if ( *test_p != strtol(argv[i],0x0,10) ){return 0;}test_p++;i++;}return 1;}

Programın okunabilir versiyonu aşağıdadır:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct tree
{
    struct tree * left;

    struct tree * right;

    int val;

} tree;


static int * test_p = 0;

void insert_root(tree ** root, int in)
{
  if (*root == NULL)
  {
    *root = (tree *)calloc(1,sizeof(tree));

    (*root)->val = in;

    return;
  }

  else if (in < (*root)->val)
  {
    insert_root(&((*root)->left),in);
  }

  else
  {
    insert_root(&((*root)->right),in);
  }
}

void preorder(tree * root)
{
    if ( root == 0x0 ) {  return; }

        *test_p++ = root->val;

        preorder(root->left);

        preorder(root->right);

}

int main(int argc, char ** argv)
{
    int test_list[argc-1];

    memset(test_list,0,argc*sizeof(int));

    test_p = test_list;

    tree * root = (tree *)calloc(1,sizeof(tree));

    root->val = strtol(argv[1],0x0,10);

    int i = 1;

    while ( argv[++i] != 0x0 )
    {
        insert_root(&root,strtol(argv[i],0x0,10));
    }

    preorder(root);

    test_p = test_list;

    i = 1;

    while ( ( i < argc ) )
    {
        if ( *test_p != strtol(argv[i],0x0,10) )
        {
            return 0;
        }

        test_p++;

        i++;
    }

    return 1;   
}

Bu programdaki ana yöntem, meşru bir ön sipariş geçişi olan (iddia edilen) sayıların listesini okur.

Çağrılan insert_root işlevi, tamsayıları önceki düğümlerin daha küçük değerler içerdiği ve sonraki düğümlerin daha büyük int değerleri içerdiği bir ikili arama ağacına ekler.

Preorder (root) işlevi, ağacı bir preorder geçişinde geçirir ve aynı anda algoritmanın int dizi test_listiyle karşılaştığı her tamsayıyı birleştirir .

Son bir süre döngü testleri de int değerlerin her eğer Stdin listeye ve bu test_list her dizinde eşdeğerdir. Bir liste unsuru ise Standart girdi ilgili indisinde test_list karşılık gelen elemanı eşleştirememişse, ana işlevi 0 döner Başka ana yöntem döner 1 .

Hangi ana döndürdüğünü belirlemek için , bash terminaline echo $ status yazın . BASH, 1 veya 0 yazdırır.


2
Puanınız beyaz alan sayıyor.
Buğday Sihirbazı,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.