สร้าง BST ที่สมดุลจาก Listed Integers


15

รับรายการจำนวนเต็มเรียงลำดับสร้างแผนภูมิการค้นหาแบบไบนารีที่สมดุลซึ่งแสดงเป็นอาร์เรย์โดยไม่ต้องใช้การสอบถามซ้ำ

ตัวอย่างเช่น:

func( [1,2,3,5,8,13,21] ) => [5,2,13,1,3,8,21]

ก่อนที่เราจะเริ่มต้นคำแนะนำ: เราสามารถทำให้ปัญหานี้ง่ายขึ้นเป็นตันเพื่อที่เราจะได้ไม่ต้องคิดเกี่ยวกับจำนวนเต็มอินพุท (หรือวัตถุใด ๆ ที่เทียบเท่าสำหรับเรื่องนั้น!)

หากเรารู้ว่ารายการอินพุตถูกเรียงลำดับแล้วเนื้อหาจะไม่เกี่ยวข้อง เราสามารถคิดถึงมันในแง่ของดัชนีไปยังอาร์เรย์เดิม

การเป็นตัวแทนภายในของอาร์เรย์อินพุตจะกลายเป็น:

func( [0,1,2,3,4,5,6] ) => [3,1,5,0,2,4,6]

นี่หมายถึงแทนที่จะเขียนสิ่งที่ต้องจัดการกับวัตถุที่เทียบเคียงได้เราเพียงแค่ต้องเขียนฟังก์ชันที่แมปจากช่วง [0, n) ไปยังอาร์เรย์ผลลัพธ์ เมื่อเรามีคำสั่งซื้อใหม่เราสามารถใช้การจับคู่กลับกับค่าในอินพุตเพื่อสร้างอาร์เรย์ส่งคืน

โซลูชั่นที่ถูกต้องจะต้อง:

  • ยอมรับอาร์เรย์ที่มีองค์ประกอบเป็นศูนย์และส่งกลับอาร์เรย์ที่ว่างเปล่า
  • ยอมรับอาร์เรย์จำนวนเต็มที่มีความยาวnและส่งคืนอาร์เรย์จำนวนเต็ม
    • ของความยาวระหว่างnและกำลังสูงสุดถัดไปคือ 2 ลบ 1 (เช่นสำหรับขนาดอินพุต 13 จะคืนค่าได้ทุกที่ระหว่าง 13 ถึง 15)
    • Array ซึ่งแสดงถึง BST โดยที่โหนดรูทอยู่ที่ตำแหน่ง 0 และความสูงเท่ากับlog (n)โดยที่ 0 แทนโหนดที่หายไป (หรือnullค่าที่เหมือนกันถ้าภาษาของคุณอนุญาต) โหนดว่างเปล่าหากมีจะต้องมีอยู่ที่ส่วนท้ายของต้นไม้ (เช่น[2,1,0])

อาร์เรย์จำนวนเต็มอินพุตมีการรับประกันต่อไปนี้:

  • ค่าเป็นจำนวนเต็มแบบ 32 บิตที่มากกว่าศูนย์
  • คุณค่านั้นไม่เหมือนใคร
  • ค่าอยู่ในลำดับจากน้อยไปมากจากตำแหน่งศูนย์
  • ค่าอาจกระจัดกระจาย (กล่าวคือไม่ติดกัน)

รหัสสั้นที่สุดโดยการนับตัวอักษร ascii ชนะ แต่ฉันก็สนใจที่จะเห็นวิธีแก้ปัญหาที่สง่างามสำหรับภาษาใด ๆ

กรณีทดสอบ

เอาท์พุทสำหรับอาร์เรย์ที่เรียบง่ายมี1การต่างๆn nตามที่อธิบายไว้ข้างต้น0s ต่อท้ายเป็นตัวเลือก

[]
[1]
[2,1,0]
[2,1,3]
[3,2,4,1,0,0,0]
[4,2,5,1,3,0,0]
[4,2,6,1,3,5,0]
[4,2,6,1,3,5,7]
[5,3,7,2,4,6,8,1,0,0,0,0,0,0,0]
[6,4,8,2,5,7,9,1,3,0,0,0,0,0,0]
[7,4,9,2,6,8,10,1,3,5,0,0,0,0,0]
[8,4,10,2,6,9,11,1,3,5,7,0,0,0,0]
[8,4,11,2,6,10,12,1,3,5,7,9,0,0,0]
[8,4,12,2,6,10,13,1,3,5,7,9,11,0,0]
[8,4,12,2,6,10,14,1,3,5,7,9,11,13,0]
[8,4,12,2,6,10,14,1,3,5,7,9,11,13,15]

คำถามทั้งหมดในเว็บไซต์นี้ไม่ว่าจะเป็นตัวต่อการเขียนโปรแกรมหรือการเขียนโค๊ดกอล์ฟควรมีเกณฑ์การชนะขั้นต้นตามวัตถุประสงค์ดังนั้นจึงเป็นไปได้ที่จะตัดสินใจได้อย่างเด็ดขาด
Howard

@Howard ขอบคุณ อัปเดตด้วยเกณฑ์ที่ชัดเจนสำหรับผู้ชนะ
Jake Wharton

1
มันจะมีประโยชน์มากที่จะมีกรณีทดสอบที่ครอบคลุมกรณียาก ๆ (แทนที่จะเป็น (ในปัจจุบัน)) เป็นกรณีที่ง่ายที่สุด
Peter Taylor

มีเหตุผลบางอย่างในการพิจารณาคำสั่งซื้อซ้ำหรือไม่ ไม่ใช่ว่าฉันกำลังมองหาโซลูชันแบบเรียกซ้ำ แต่ดูเหมือนว่าเป็นสิ่งประดิษฐ์และไม่จำเป็น
dmckee --- ผู้ดูแลอดีตลูกแมว

1
มีคนอธิบายได้ว่ารายการนี้เป็น BST อย่างไร
justinpc

คำตอบ:


4

ทับทิม , 143

s=ARGV.size;r,q=[],[[0,s]];s.times{b,e=q.shift;k=Math::log2(e-b).to_i-1;m=(e-b+2)>(3<<k)?b+(2<<k)-1:e-(1<<k);r<<ARGV[m];q<<[b,m]<<[m+1,e]};p r

มันเป็นรุ่นที่บีบอัด (หลวม) ของรหัสต่อไปนี้ซึ่งโดยทั่วไปจะเป็น BFS บนต้นไม้

def l(n)
    k = Math::log2(n).to_i-1
    if n+2 > (3<<k) then
        (2<<k)-1
    else
        n-(1<<k) 
    end
end

def bfs(tab)
  result = []
  queue = [[0,tab.size]]
  until queue.empty? do
    b,e = queue.shift
    m = b+l(e-b)
    result << tab[m]
    queue << [b,m] if b < m
    queue << [m+1,e] if m+1 < e
  end
  result
end

p bfs(ARGV)

นอกจากนี้เนื่องจากเป็น BFS ไม่ใช่ DFS ข้อกำหนดของโซลูชันที่ไม่เรียกซ้ำไม่สำคัญและทำให้บางภาษาเสียเปรียบ

แก้ไข:แก้ไขปัญหาขอบคุณ @PeterTaylor สำหรับความคิดเห็นของเขา!


@PeterTaylor ความตั้งใจคือการวาง 3 ทางซ้ายของ 4 แต่ไม่มีช่องว่างดังนั้นจึงผิด ขอบคุณสำหรับการชี้ให้เห็น!
dtldarek

@PeterTaylor แก้ไขอาหารกลางวันมันน่าจะใช้ได้แล้ว
dtldarek

4

Java , 252

ตกลงนี่คือความพยายามของฉัน ฉันได้เล่นกับการทำงานของบิตและฉันมาด้วยวิธีการคำนวณดัชนีขององค์ประกอบใน BST จากดัชนีในอาร์เรย์เดิม

รุ่นบีบอัด

public int[]b(int[]a){int i,n=1,t;long x,I,s=a.length,p=s;int[]r=new int[(int)s];while((p>>=1)>0)n++;p=2*s-(1l<<n)+1;for(i=0;i<s;i++){x=(i<p)?(i+1):(p+2*(i-p)+1);t=1;while((x&1<<(t-1))==0)t++;I=(1<<(n-t));I|=((I-1)<<t&x)>>t;r[(int)I-1]=a[i];}return r;}

รุ่นยาวดังต่อไปนี้ด้านล่าง

public static int[] makeBst(int[] array) {
  long size = array.length;
  int[] bst = new int[array.length];

  int nbits = 0;
  for (int i=0; i<32; i++) 
    if ((size & 1<<i)!=0) nbits=i+1;

  long padding = 2*size - (1l<<nbits) + 1;

  for (int i=0; i<size; i++) {
    long index2n = (i<padding)?(i+1):(padding + 2*(i-padding) + 1);

    int tail=1;
    while ((index2n & 1<<(tail-1))==0) tail++;
    long bstIndex = (1<<(nbits-tail));
    bstIndex = bstIndex | ((bstIndex-1)<<tail & index2n)>>tail;

    bst[(int)(bstIndex-1)] = array[i];
  }
 return bst;
}

คุณต้องมีการนับจำนวนตัวอักษรและสิ่งนี้ไม่ได้อยู่ในสนามกอล์ฟ
dmckee --- ผู้ดูแลอดีตลูกแมว

@dmckee ฉันได้แก้ไขโพสต์เพื่อรวมเวอร์ชันที่บีบอัดและจำนวนตัวอักษร
mikail sheikh

แสดงที่ดี ฉันจะพนันได้เลยว่าช่องว่างเหล่านั้นไม่จำเป็น ใน c int[] b(int[] a)ก็แสดงได้เช่นint[]b(int[]a)กัน
dmckee --- ผู้ดูแลอดีตลูกแมว

คุณมีa.lengthในการจัดสรรอาเรย์ sเปลี่ยนไป กำจัดพื้นที่ระหว่างfor (หลาย ๆ ครั้ง แต่ละวงจะสร้างและint i=0 int t=0สร้างด้วยn( int n=0,i,t;) แล้วเพียงแค่i=0ลูปและt=1ภายใน ประกาศด้านในlong xและlong Iด้วยsและเพิ่งเริ่มต้นในการวนรอบ ( long s=a.length,I,x;และx=../ I=..) &คุณไม่ควรจะต้องมีช่องว่างรอบไบนารีและ
Jake Wharton

นอกจากนี้ยังI=I|..สามารถเขียนได้I|=..
Jake Wharton

3
def fn(input):
    import math
    n = len(input)
    if n == 0:
        return []
    h = int(math.floor(math.log(n, 2)))
    out = []
    last = (2**h) - 2**(h+1) + n

    def num_children(level, sibling, lr):
        if level == 0:
            return 0
        half = 2**(level-1)
        ll_base = sibling * 2**level + lr * (half)
        ll_children = max(0, min(last, ll_base + half - 1) - ll_base + 1)
        return 2**(level-1) - 1 + ll_children

    for level in range(h, -1, -1):
        for sibling in range(0, 2**(h-level)):
            if level == 0 and sibling > last:
                break
            if sibling == 0:
                last_sibling_val = num_children(level, sibling, 0)
            else:
                last_sibling_val += 2 + num_children(level, sibling - 1, 1) \
                    + num_children(level, sibling, 0)
            out.append(input[last_sibling_val])
    return out

2

ไม่แน่ใจว่าสิ่งนี้ตรงกับความต้องการของคุณของโหนดว่างเปล่าที่ตอนท้ายของต้นไม้และแน่นอนว่ามันจะไม่ชนะรางวัลใด ๆ สำหรับช่วงเวลาสั้น ๆ แต่ฉันคิดว่ามันถูกต้องและมีกรณีทดสอบ :)

public class BstArray {
    public static final int[] EMPTY = new int[] { };
    public static final int[] L1 = new int[] { 1 };
    public static final int[] L2 = new int[] { 1, 2 };
    public static final int[] L3 = new int[] { 1, 2, 3 };
    public static final int[] L4 = new int[] { 1, 2, 3, 5 };
    public static final int[] L5 = new int[] { 1, 2, 3, 5, 8 };
    public static final int[] L6 = new int[] { 1, 2, 3, 5, 8, 13 };
    public static final int[] L7 = new int[] { 1, 2, 3, 5, 8, 13, 21 };
    public static final int[] L8 = new int[] { 1, 2, 3, 5, 8, 13, 21, 35 };
    public static final int[] L9 = new int[] { 1, 2, 3, 5, 8, 13, 21, 35, 56 };
    public static final int[] L10 = new int[] { 1, 2, 3, 5, 8, 13, 21, 35, 56, 91 };

    public static void main(String[] args) {
        for (int[] list : Arrays.asList(EMPTY, L1, L2, L3, L4, L5, L6, L7, L8, L9, L10)) {
            System.out.println(Arrays.toString(list) + " => " + Arrays.toString(bstListFromList(list)));
        }
    }

    private static int[] bstListFromList(int[] orig) {
        int[] bst = new int[nextHighestPowerOfTwo(orig.length + 1) - 1];

        if (orig.length == 0) {
            return bst;
        }

        LinkedList<int[]> queue = new LinkedList<int[]>();
        queue.push(orig);

        int counter = 0;
        while (!queue.isEmpty()) {
            int[] list = queue.pop();
            int len = list.length;

            if (len == 1) {
                bst[counter] = list[0];
            } else if (len == 2) {
                bst[counter] = list[1];
                queue.add(getSubArray(list, 0, 1));
                queue.add(new int[] { 0 });
            } else if (len == 3) {
                bst[counter] = list[1];
                queue.add(getSubArray(list, 0, 1));
                queue.add(getSubArray(list, 2, 1));
            } else {
                int divide = len / 2;
                bst[counter] = list[divide];
                queue.add(getSubArray(list, 0, divide));
                queue.add(getSubArray(list, divide + 1, len - (divide + 1)));
            }
            counter++;
        }

        return bst;
    }

    private static int nextHighestPowerOfTwo(int n) {
        n--;
        n |= n >> 1;
        n |= n >> 2;
        n |= n >> 4;
        n |= n >> 8;
        n |= n >> 16;
        n++;

        return n;
    }

    private static int[] getSubArray(int[] orig, int origStart, int length) {
        int[] list = new int[length];
        System.arraycopy(orig, origStart, list, 0, length);
        return list;
    }
}

2

Golfscript ( 99 89)

~]:b[]:^;{b}{{:|.,.2base,(2\?:&[-)&2/]{}$0=&(2/+:o[=]^\+:^;|o<.!{;}*|o)>.!{;}*}%:b}while^p

โดยทั่วไปแล้วพอร์ตตรงของโซลูชัน Python ของฉันทำงานในลักษณะเดียวกัน

สามารถปรับปรุงให้ดีขึ้นได้เล็กน้อยด้วย "golfisms" ที่มากขึ้นโดยปรับปรุงแล้วโดย 10 ตัวอักษรด้วยอินพุตของ @ petertaylor :)


ฉันคิดว่ามันควรจะเป็นไปได้ในไม่เกิน 70 แม้ว่าฉันจะยังไม่ได้ตอบ GolfScript ของฉันค่อนข้างเสร็จ แม้ว่าจะมีการปรับปรุงที่ง่ายสำหรับคุณ !{;}{}ifก็สามารถจะเป็น!{;}*เพราะ!การค้ำประกันที่จะกลับมาหรือ0 1คุณสามารถใช้ราชสกุลที่ไม่ใช่ตัวอักษรสำหรับตัวแปรดังนั้นถ้าคุณใช้^แทนr, |แทนx, &แทนyคุณสามารถลดช่องว่างทั้งหมดที่
Peter Taylor

@PeterTaylor ขอบคุณไม่ทราบเกี่ยวกับตัวแปรและตัวเลขบุหรี่, ยังใหม่มากที่จะ golfscript :)
โจอาคิม Isaksson

2

Java 192

ดัชนีแผนที่ในอินพุตไปยังดัชนีในเอาต์พุต

int[]b(int[]o){int s=o.length,p=0,u=s,i=0,y,r[]=new int[s],c[]=new int[s];while((u>>=1)>0)p++;for(int x:o){y=p;u=i;while(u%2>0){y--;u/=2;}r[(1<<y)-1+c[y]++]=x;i+=i>2*s-(1<<p+1)?2:1;}return r;}

รุ่นยาว:

static int[] bfs(int[] o) {
  int rowCount = 32 - Integer.numberOfLeadingZeros(o.length); // log2
  int slotCount = (1<<rowCount) - 1; // pow(2,rowCount) - 1

  // number of empty slots at the end
  int emptySlots = slotCount - o.length;
  // where we start to be affected by these empty slots
  int startSkippingAbove = slotCount - 2 * emptySlots; // = 2 * o.length - slotCount

  int[] result = new int[o.length];
  int[] rowCounters = new int[rowCount]; // for each row, how many slots in that row are taken
  int i = 0; // index of where we would be if this was a complete tree (no trailing empty slots)
  for (int x : o) {
    // the row (depth) a slot is in is determined by the number of trailing 1s
    int rowIndex = rowCount - Integer.numberOfTrailingZeros(~i) - 1;
    int colIndex = rowCounters[rowIndex]++; // count where we are
    int rowStartIndex = (1 << rowIndex) - 1; // where this row starts in the result array

    result[rowStartIndex + colIndex] = x;

    i++;
    // next one has to jump into a slot that came available by not having slotCount values
    if (i > startSkippingAbove) i++;
  }

  return result;
}

2

Wolfram Mathematica 11, 175 Bytes

g[l_]:=(x[a_]:=Floor@Min[i-#/2,#]&@(i=Length[a]+1;2^Ceiling@Log2[i]/2);Join@@Table[Cases[l//.{{}->{},b__List:>(n[Take[b,#-1],b[[#]],Drop[b,#]]&@x[b])},_Integer,{m}],{m,x[l]}])

ฟังก์ชั่นg[l]รับเป็นอินพุต a List(เช่นl={1,2,3,4,...}) และส่งคืนListฟอร์มที่ต้องการ มันทำงานได้ดังต่อไปนี้:

  • x[a_]:=Floor@Min[i-#/2,#]&@(i=Length[a]+1;2^Ceiling@Log2[i]/2) รับรายการและค้นหารูทของ BST ที่เกี่ยวข้อง
    • i=Length[a]+1 ทางลัดสำหรับความยาวของรายการ
    • 2^Ceiling@Log2[i]/2 ขอบเขตบนของค่าของรูต
    • Min[i-#/2,#]&@(...)อาร์กิวเมนต์ขั้นต่ำสุดของทั้งสองซึ่ง#หมายถึงสิ่งที่อยู่ภายใน(...)
  • l//.{...} ใช้กฎการแทนที่ที่ตามมาซ้ำ ๆ l
  • {}->{} ไม่มีสิ่งที่ต้องทำ (นี่คือกรณีขอบเพื่อหลีกเลี่ยงการวนซ้ำไม่สิ้นสุด)
  • b__List:>(n[Take[b,#-1],b[[#]],Drop[b,#]]&@x[b])แยกListออกเป็น{{lesser}, root, {greater}}
  • Cases[...,_Integer,{m}] ใช้จำนวนเต็มทั้งหมดที่ระดับ (ความลึก) m
  • Table[...,{m,1,x[l]}]สำหรับทั้งหมดmจนถึงx[l](ซึ่งเกินความจำเป็นจริงๆ)

มันสามารถทดสอบได้โดยการทำงาน

Table[g[Range[a]], {a, 0, 15}]//MatrixForm

การใช้งานนี้ไม่รวมศูนย์ต่อท้าย


1

Python ( 175 171)

อัดแน่นพอสมควรยังคงสามารถอ่านได้

def f(a):
 b=[a]
 while b:
  c,t=((s,2**(len(bin(len(s)))-3))for s in b if s),[]
  for x,y in c:
   o=min(len(x)-y+1,y/2)+(y-1)/2
   yield x[o]
   t+=[x[:o],x[o+1:]]
  b=t

มันให้ผลลัพธ์กลับมาเพื่อให้คุณสามารถวนซ้ำมันหรือ (เพื่อจุดประสงค์ในการแสดงผล) พิมพ์เป็นรายการ

>>> for i in range(1,17): print i-1,list(f(range(1,i)))
 0 []
 1 [1]
 2 [2, 1]
 3 [2, 1, 3]
 4 [3, 2, 4, 1]
 5 [4, 2, 5, 1, 3]
 6 [4, 2, 6, 1, 3, 5]
 7 [4, 2, 6, 1, 3, 5, 7]
 8 [5, 3, 7, 2, 4, 6, 8, 1]
 9 [6, 4, 8, 2, 5, 7, 9, 1, 3]
10 [7, 4, 9, 2, 6, 8, 10, 1, 3, 5]
11 [8, 4, 10, 2, 6, 9, 11, 1, 3, 5, 7]
12 [8, 4, 11, 2, 6, 10, 12, 1, 3, 5, 7, 9]
13 [8, 4, 12, 2, 6, 10, 13, 1, 3, 5, 7, 9, 11]
14 [8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13]
15 [8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15]

@dtldarek ความคิดเห็นของเขาดูเหมือนว่าจะถูกลบ แต่ดูเหมือนว่าจะผ่านกรณีทดสอบในขณะนี้
Joachim Isaksson

ฉันลบความคิดเห็นของฉันเพื่อมิให้ผู้คนงดการ upvoting @ dtldarek เพราะความคิดเห็นที่บอกว่าเป็นรถ
Peter Taylor

@PeterTaylor ขอขอบคุณสำหรับการพิจารณาของคุณ ;-)
dtldarek

1

ชวา

นี่เป็นวิธีการคำนวณโดยตรง ฉันคิดว่ามันใช้งานได้ แต่มันมีผลข้างเคียงที่ไม่มีพิษภัยในทางปฏิบัติอย่างใดอย่างหนึ่ง อาร์เรย์ที่สร้างขึ้นอาจเสียหาย แต่ไม่มีในทางที่จะมีผลต่อการค้นหา แทนที่จะสร้างโหนด 0 (null) มันจะสร้างโหนดที่ไม่สามารถเข้าถึงได้ซึ่งเป็นโหนดที่จะพบได้ก่อนหน้านี้ในทรีระหว่างการค้นหา มันทำงานได้โดยการจับคู่อาร์เรย์ดัชนีของกำลังการค้นหาปกติของขนาดแผนภูมิการค้นหาแบบไบนารีขนาด 2 ลงบนอาร์เรย์แบบแผนภูมิการค้นหาแบบไบนารีที่มีขนาดไม่สม่ำเสมอ อย่างน้อยฉันคิดว่ามันใช้งานได้

import java.util.Arrays;

public class SortedArrayToBalanceBinarySearchTreeArray
{
    public static void main(String... args)
    {
        System.out.println(Arrays.toString(binarySearchTree(19)));
    }

    public static int[] binarySearchTree(int m)
    {
        int n = powerOf2Ceiling(m + 1);
        int[] array = new int[n - 1];

        for (int k = 1, index = 1; k < n; k *= 2)
        {
            for (int i = 0; i < k; ++i)
            {
                array[index - 1] = (int) (.5 + ((float) (m)) / (n - 1)
                        * (n / (2 * k) * (1 + 2 * index) - n));
                ++index;
            }
        }

        return array;
    }

    public static int powerOf2Ceiling(int n)
    {
        n--;
        n |= n >> 1;
        n |= n >> 2;
        n |= n >> 4;
        n |= n >> 8;
        n |= n >> 16;
        n++;

        return n;
    }

}

นี่เป็นเวอร์ชั่นย่อ (มากกว่าฟังก์ชั่นและชื่อที่จับคู่กัน) มันยังมีพื้นที่สีขาว แต่ฉันไม่กังวลเกี่ยวกับการชนะ นอกจากนี้เวอร์ชันนี้ใช้อาร์เรย์จริง อีกอันหนึ่งเพิ่งเอา int สำหรับดัชนีที่สูงที่สุดในอาร์เรย์

public static int[] b(int m[])
{
    int n = m.length;
    n |= n >> 1;
    n |= n >> 2;
    n |= n >> 4;
    n |= n >> 8;
    n |= n >> 16;
    n++;

    int[] a = new int[n - 1];

    for (int k = 1, j = 1, i; k < n; k *= 2)
    {
        for (i = 0; i < k; ++i)
        {
            a[j - 1] = m[(int) (.5 + ((float) m.length) / (n - 1)
                    * (n / (2 * k) * (1 + 2 * j) - n)) - 1];
            ++j;
        }
    }

    return a;
}

เนื่องจากนี่เป็นโค้ดกอล์ฟให้ย่อวิธี / ชื่อ / ฯลฯ ให้สั้นที่สุดเท่าที่จะทำได้ ลบช่องว่างทั้งหมด (และวิธีการ / วัสดุที่ไม่จำเป็น) และใส่จำนวนตัวอักษร มิฉะนั้นคุณทำได้ดี
Justin

@ Jake Wharton ฉันอยากเห็นโซลูชันการแมปโดยตรงของคุณจริงๆ ฉันไม่แน่ใจ 100% ของฉันทำงานสำหรับอาร์เรย์ที่มีขนาดใหญ่มากเพราะมันขึ้นอยู่กับการทำแผนที่ทางคณิตศาสตร์อย่างต่อเนื่องที่มีค่าได้รับการปัดเศษ ดูเหมือนว่าจะใช้ได้ แต่ฉันไม่แน่ใจว่าจะพิสูจน์ได้อย่างไร
metaphyze

1

GolfScript ( 79 77 70 ตัวอักษร)

เนื่องจากตัวอย่างในคำถามใช้ฟังก์ชันฉันจึงทำฟังก์ชันนี้ การถอด{}:f;ออกจากนิพจน์ที่รับอินพุตบนสแต็กและปล่อย BST บนสแต็กจะบันทึก 5 ตัวอักษร

{[.;][{{.!!{[.,.)[1]*{(\(@++}@(*1=/()\@~]}*}%.{0=}%\{1>~}%.}do][]*}:f;

การสาธิตออนไลน์ (หมายเหตุ: แอพอาจจะอุ่นขึ้น: หมดเวลาสองครั้งสำหรับฉันก่อนที่จะทำงานใน 3 วินาที)

ด้วยช่องว่างเพื่อแสดงโครงสร้าง:

{
    # Input is an array: wrap it in an array for the working set
    [.;]
    [{
        # Stack: emitted-values working-set
        # where the working-set is essentially an array of subtrees
        # For each subtree in working-set...
        {
            # ...if it's not the empty array...
            .!!{
                # ...gather into an array...
                [
                    # Get the size of the subtree
                    .,
                    # OEIS A006165, offset by 1
                    .)[1]*{(\(@++}@(*1=
                    # Split into [left-subtree-plus-root right-subtree]
                    /
                    # Rearrange to root left-subtree right-subtree
                    # where left-subtree might be [] and right-subtree might not exist at all
                    ()\@~
                ]
            }*
        }%
        # Extract the leading element of each processed subtree: these will join the emitted-values
        .{0=}%
        # Create a new working-set of the 1, or 2 subtrees of each processed subtree
        \{1>~}%
        # Loop while the working-set is non-empty
        .
    }do]
    # Stack: [[emitted values at level 0][emitted values at level 1]...]
    # Flatten by joining with the empty array
    []*
}:f;

1

J , 52 ไบต์

t=:/:(#/:@{.(+:,>:@+:@i.@>:@#)^:(<.@(2&^.)@>:@#`1:))

ฟังก์ชั่นใช้รายการเรียงลำดับและส่งกลับในลำดับต้นไม้ไบนารี

สังเกตว่าต้นไม้มีรูปร่างเหมือนกัน แต่ระดับล่างจะสั้นลง

  • `1: เริ่มต้นด้วย 1
  • <.@(2&^.)@>:@# วนซ้ำตามพื้นของ log2 (ความยาว + 1)
  • +: , >:@+:@i.@>:@# วนซ้ำ: ผนวกสองครั้งของเวกเตอร์สุดท้ายด้วยจำนวนคี่ 1,3 .. 2 * ความยาว + 1
  • # /:@{. ใช้จำนวนรายการที่ต้องการเท่านั้นและรับดัชนีการจัดเรียงของพวกเขา
  • /: ใช้ดัชนีการเรียงลำดับเหล่านั้นกับอินพุตที่กำหนด

TIO


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.