これはBSTの先行予約の走査ですか?


21

バックグラウンド

バイナリツリーは、そのすべてのノード最大2人の子供に持ってルート権限を取得し、ツリーです。

標識された二分木は、そのすべてのノードは正の整数で標識された二分木です。さらに、すべてのラベルは区別されます。

BST(バイナリ検索ツリー)は、各ノードのラベルは、その左の部分木のすべてのノードのラベルよりも大きく、その右サブツリーの全てのノードのラベルよりも小さくなっている標識された二分木です。たとえば、次はBSTです。

BST

ラベル付きバイナリツリーの事前順序走査は、次の擬似コードによって定義されます。

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

より良い直観を得るには、次の画像を参照してください。

BTの先行予約走査

このバイナリツリーの頂点は、次の順序で印刷されます。

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

BSTについての詳細はこちら、先行予約の走査についての詳細はこちらをご覧ください

チャレンジ

整数のリストを考えると、あなたのタスクは、その正確プリオーダートラバーサルプリントBSTがあるかどうかを決定することです。aa

入力

  • 明確な正の整数aの空でないリストa
  • オプションで、aの長さ。

出力

  • truthyの値があれば、いくつかのBSTのプリオーダートラバーサルです。a
  • falseyのそれ以外の値。

ルール

  • 有効な提出I / O抜け穴の標準ルールが適用されます。
  • これはであるため、最短のソリューション(バイト単位)が優先されます。いつものように、ゴルフ言語のとてつもなく短い解決策で、選択した言語で長い回答を投稿することを妨げないでください。
  • これはルールではありませんが、ソリューションをテストするためのリンクとそれがどのように機能するかの説明が含まれていれば、あなたの答えはよりよく受け取られます。

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

このリンクをチェックしKevin Cruijssen提供)、例を視覚的に確認してください。



すべての整数が正であると仮定できますか?
GB

@GBはい。今すぐ投稿を編集します。
Delfad0r

回答:


11

JavaScript(Node.js)、49バイト

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

オンラインでお試しください!

配列a0an1、IFF一部BSTのプリオーダートラバーサルある0 I < J < N a i < a j 1a0<j<n;a<aj1a<ajが成り立つ。

Arnauldのおかげで、1バイト節約できます。


8

ゼリー、7バイト

ŒPŒ¿€4ḟ

オンラインでお試しください!

[4]トラバーサルの場合は、それ以外の場合を返します[]

基本的にtshのアルゴリズムを使用します。予約注文のトラバースの「不適格」条件は、[mid、high、low]のような3つの要素のサブシーケンスです。(たとえば、[20、30、10]。)

我々は、同等の任意のサブシーケンスを確認任意のインデックス有する長さ4のすべてのリストは次のようにソートされ、それらの置換リストに、[ 1 ... k個の CDB]ここで、A iはソートされ、I <B <C <D 。(最後の3つの要素を見ると、そのようなリストはそれぞれ失格であり、各失格リストは明らかにこの形式です。)

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

証明

先行予約トラバーサルには、不適格なサブシーケンスは含まれません

基本ケース:traversal(•)は空のリストです。✓

誘導:traversal(t)は:t.root ++ traversal(t.left) ++ traversal(t.right)です。

してみましょう[a、b、c]のサブシーケンスの明細書のこと。私たちは紹介し、C <A <Bは不可能です。

  • 場合t.rootは=、その後<A <B cが必要とC∈t.leftB∈t.rightをので、[A、B、C]は、間違った順序です。
  • 場合は、A、B、C∈t.leftまたは、B、C∈t.right、帰納法の仮定を使用します。
  • もし∈t.leftC∈t.rightその後、C>

サブシーケンスを不適格としない個別の整数のリストは、BSTの先行順走査です。

リストが空の場合、それはささいなBSTのトラバースです。

リストの先頭末尾が続く場合:

  • してみましょう以下の最長プレフィックスもより少ない要素の頭部、と聞かせてより多くのリストの残りなります。
  • 次に、more [1]> head、およびその他のすべてのmore [i]headより大きい(そうでない場合は[head、more [1]、more [i]]は不適格なサブシーケンスになります)。
  • 再帰:ターン以下より分探索木に。
  • 今、私たちのリストは

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

    このツリーは有効なBSTです。


1
いい証拠だ。実際、私は答えを投稿するときに式を証明しませんでした。入力からBSTを構築しようと試みた後、それが正しいと感じました。
tsh

5

Java 10、94バイト

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

のポート @tsh 'JavaScript回答の

オンラインでお試しください。

説明:

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ブール値をで再割り当てできるTIL |=。私&=も動作すると思いますか?
J.サール

J.Salléうん、両方の@ |=&=のショートカットとしての仕事b = b | conditionb = b & condition&および|ためのショートカットです&&し、||もちろん、ほとんどの場合)。
ケビンクルーイッセン

5

ルビー46 40 38バイト

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

オンラインでお試しください!

これは、最初の要素aをピボットとして再帰的に取得し、配列の残りの部分を2つに分割できるかどうかを確認することで機能します(交差と結合を使用:最初にすべての要素を削除し、次に右側に再度追加して、何かがあるかどうかを確認しますかわった)。


3

Retina 0.8.2、31バイト

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

オンラインでお試しください!リンクにはテストケースが含まれます。@tshのアルゴリズムを使用します。説明:

\d+
$*

単項に変換します。

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

連続する2つの連続した降順の数値の間にある数値を見つけます。

^0

一致の数がゼロであることを確認してください。




3

Scala(68 67バイト)

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

オンラインで試す

@nwellnhofの回答のポート。

Scala(122 103バイト)

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

両方のソリューションを短くするための提案をしてくれた@Laikoniに感謝します。

オンラインで試す

説明:

  1. (Scalaを使用してspan)スライスの基準として配列の頭を使用して配列をスライスします。
  2. 配列の最初のスライスがヘッドより小さく、2番目のスライスがヘッドより大きいことを確認します。
  3. 各スライスが(2)を満たしていることを再帰的に確認します

1
私はあなたがスペースを必要としないと思いますval (s,t)trueすることができ1>0、あなたがドロップすることができs.forall(_<i(0))&、これはすでにによって保証されるべきですspan
ライコニ

1
あなたは、関数を呼び出すことができ%、スペースをドロップしますdef%(i:Seq[Int])=
Laikoni

ソリューションには、他とは異なる関数の宣言が含まれています。純粋な表現は非常に短いです。;)
Dr Y Wit

私はtshの答えを移植しようとしていましたが、それを十分に短くすることができませんでした。バージョン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)}。バージョン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)。これらを短くする方法はありますか?
Dr Y Wit

単純な英語のアルゴリズム:各要素に対して、要素のすべてのペアが互いに隣り合っているかどうかをチェックします。
Dr Y Wit

2

05AB1E15 10 バイト

ŒεD{3.IÊ}P

@リンののJelly回答の@Emignaの
おかげで-5バイト。

オンラインそれを試してみたり、すべてのテストケースを確認してください

説明: "

Œ             # 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
どうŒεD{3.IÊ}P
エミグナ

1
@Emignaええ、それは確かにはるかに簡単でしょう...>。>ありがとう!:)(そして良い週末を。)
ケビンクルーッセン

2

ハスケル、41バイト

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

オンラインでお試しください!

mid..high..lowのサブシーケンスがないことをチェックするだけで十分であるというリンの観察を使用します。。これは、各要素hについて、t後に<h続く要素のリストが要素のブロックであり、その後に要素のブロックが続くことを意味します>h(両方のブロックが空の場合があります)。だから、我々は要素の接頭辞ドロップした後、そのコードのチェック<hではt、残りの要素が全てです>hhリストの長さが1になるまで、初期要素ごとにこれをチェックします。

単純化の可能性としては、最後の2つが連続している場合にサブパターンmid..high、lowをチェックするだけで十分です。残念ながら、Haskellにはパターンマッチで前から行うことができるように、最後の2つの要素を抽出する短い方法がありませんa:b:c中、高、低をチェックする短いソリューションを見つけましたが、これはなどの入力を拒否できません[3,1,4,2]

Laikoniから取得したフォーマット済みテストケース。


1

Japt、14バイト

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

ジャプト通訳

出力 falseBSTの、trueなし。

説明:

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

スカラ

すべてのアプローチは、tshで示されるルールの実装です。

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)

式ではなく関数でなければならない場合、各行は(17バイト)で始まる必要があります

def%(l:Seq[Int])=

0

Oracle SQL、177バイト

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にはブール型がないため、queryは1または0を返します。

Oracle SQL 12c、210バイト

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)

PL / SQLと同じ方法でSQLの配列の要素にアクセスすることはできません。つまり、a(i)です。したがって、そのために関数fが宣言されwith clauseました。そうでなければ、解決策ははるかに短かったでしょう。

その他の制限

  • (1を返す代わりに)3要素より短い配列に対して例外をスローします
  • powermultiset_by_cardinalityはドキュメントに明示的に記載されていない場合でも順序を保持するという仮定があります

sqlplusリスト

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

オンライン検証apex.oracle.com

更新

Oracle SQL、155バイト

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バイト(空白文字はカウントしません); 923バイト(空白を含む)

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

プログラムの読み取り可能なバージョンは次のとおりです。

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

このプログラムのメインメソッドは、(疑いなく)正当な事前順序走査である番号のリストを読み取ります。

呼び出される関数insert_rootは、前のノードの値がより小さく、次のノードの値がより大きなint値であるバイナリ検索ツリーに整数を挿入します。

関数preorder(root)は、preorderトラバーサルでツリーをトラバースし、アルゴリズムがint配列test_listに到達する各整数を同時に連結します

最後のwhileループは、stdinリストの各int値とtest_listの各int値が各インデックスで等しいかどうかをテストします。stdinからリスト要素がある場合それぞれのインデックスでtest_listの対応する要素と一致しない、main関数は0を返します。それ以外の場合、mainメソッドは1を返します。。

メインが何を返したかを判断するには、bashターミナルにecho $ statusと入力します。BASHは1または0を出力します。


2
あなたのスコアは空白を数えるものです。
ウィートウィザード
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.