Làm thế nào để một cách hiệu quả tạo ra tất cả các chuỗi nhị phân với số lượng bằng 0 và 1 bằng nhau?


10

Một chuỗi nhị phân có độ dài n chỉ là một chuỗi các lệnh để mỗi hoặc là hoặc . Để tạo tất cả các chuỗi nhị phân như vậy, người ta có thể sử dụng cấu trúc cây nhị phân rõ ràng theo cách sau: gốc là "rỗng", nhưng mỗi con trái tương ứng với việc thêm vào chuỗi hiện có và mỗi con phải vào . Bây giờ, mỗi chuỗi nhị phân chỉ đơn giản là một đường dẫn có độ dài bắt đầu từ gốc và kết thúc tại một chiếc lá. 0 1 0 1 n + 1x1,Giáo dục,xnxj0101n+1

Đây là câu hỏi của tôi:

Chúng ta có thể làm tốt hơn nếu chúng ta chỉ muốn tạo tất cả các chuỗi nhị phân có độ dài có chính xác số 0 và không?n n2nnn

Bằng cách "chúng ta có thể làm tốt hơn", ý tôi là chúng ta nên có độ phức tạp thấp hơn thuật toán ngớ ngẩn trước tiên xây dựng toàn bộ cây ở trên và sau đó cố gắng tìm các đường dẫn đó với số cạnh "trái" và "phải" bằng nhau.


Bạn có thể tìm ra cách tạo hiệu quả tất cả các chuỗi tăng số nghiêm ngặt trong phạm vi từ 1 đến 2 n không? n2n
Thương hiệu Cornelius

Tôi không thể nhận xét về độ phức tạp, nhưng thuật toán ngây thơ của tôi sẽ tạo ra các bước đi dọc theo các cạnh của lưới ô vuông từ một góc đến một đường chéo, sử dụng loại sơ đồ quay lui. Điều đó có nghĩa là 01 và 10 kết thúc ở cùng một vị trí (không giống như cây của bạn) nhưng với backtrack, chúng tôi biết lịch sử này.
Hendrik ngày

Trên một lưu ý có thể khác, đây là một triển khai Java của select -iterator . (nk)
Pål GD

Câu trả lời:


6

Rõ ràng có chuỗi nhị phân có độ dài . Để duyệt qua nhị phân, thuật toán phải truy cập mỗi nút một lần, tức là nó phải thực hiện các bước. 2 n 2 n i = 0 2 i = 2 2 n + 1 - 1 = O ( 4 n )4n2n

ΣTôi= =02n2Tôi= =22n+1-1= =Ôi(4n)

Chúng ta hãy xem xét một thuật toán đệ quy đi ngang qua cây bạn đã mô tả, nhưng đếm số lượng và số không trên đường đi, tức là nó sẽ chỉ đi qua phần tốt của cây.
Nhưng có bao nhiêu chuỗi nhị phân như vậy với 0 'và 1'? Chúng tôi chọn 1 cho chuỗi có độ dài và sử dụng công thức của Stirling trong bước 2: n n 2 n ( 2 nnnn2n

(2nn)= =(2n)!(n!)2= =4nπn(1+Ôi(1/n))

EDIT
Nhờ nhận xét của Peter Shor, chúng tôi cũng có thể phân tích số bước cần thiết của thuật toán thứ hai, tính cả 1 và 0. Tôi đang trích dẫn bình luận của anh ấy từ bên dưới:

Chúng tôi muốn tìm tất cả các chuỗi nhị phân với chính xác 0 và 1. Chúng tôi đi qua cây nhị phân trong đó mỗi nút là một chuỗi nhiều nhất là 0 và 1. Chúng tôi không cần phải truy cập bất kỳ nút nào có nhiều hơn 0 hoặc hơn 1. Có bao nhiêu nút chúng ta cần phải truy cập? Có các chuỗi với 0's và 1's. Tổng kết điều này trên tất cả cho . Bây giờ, chúng ta cần truy cập từng nút này với chi phí trung bình không đổi trên mỗi nút. Chúng ta có thể làm điều này bằng cách đến thăm từng đứa trẻ bên trái trước, và mỗi đứa trẻ bên phải thứ hai.n 2 n n n ( i + jnn2nnn iji,jnΣ n i = 0 Σ n j = 0 ( i + j(Tôi+jTôi)TôijTôi,jnΣTôi= =0nΣj= =0n(Tôi+jTôi)= =(2n+2n+1)-1

Sử dụng lại công thức của Stirling, chúng tôi thu được là thời gian chạy của thuật toán mới.

(2n+2n+1)-1= =4n+11n+1(1+Ôi(1/n))-1= =Ôi(4nn)

Bạn phải cẩn thận hơn một chút. Có lẽ sau khi tạo từng chuỗi, chúng tôi xử lý chuỗi đó trong thời gian . Vì vậy, chỉ cần xử lý tất cả các chuỗi cân bằng sẽ mất thời gian . Nếu thuật toán tạo "ngớ ngẩn" được tối ưu hóa thực sự là , thì không có gì có thể đạt được bằng cách chuyển sang một thuật toán thông minh hơn, ngoài các cơ hội cho các lỗi. Ω(n)Ω(4nn)Ôi(4n)
Yuval Filmus

@Yuval Filmus: Chính xác thì ý bạn là "xử lý chuỗi" là gì? Nếu bạn có nghĩa là thời gian dành cho đầu ra, chắc chắn là , thì bạn phải xem xét yếu tố đó trong thời gian chạy của thuật toán "ngớ ngẩn", sau đó là . Θ(n)Ôi(4nn)
tranisstor

2
Quan điểm của tôi là nếu bạn quan tâm đến sự khác biệt giữa và , thì tối thiểu bạn phải nêu thời gian chạy chính xác; không đủ để tiết lộ bất kỳ sự khác biệt tiềm năng nào giữa hai thuật toán. Ngoài ra, bạn phải cẩn thận phân tích thuật toán mới được đề xuất của mình, để thấy rằng các yếu tố nhỏ "không đáng kể" này không làm cho nó chậm hơn thuật toán tầm thường. 4n4n/nÔi~(4n)
Yuval Filmus

2
Làm thế nào để bạn chỉ xây dựng "phần tốt" của cây mà không phải bao gồm cả "phần xấu"? Bạn cần bao gồm tất cả các nút của cây không có nhiều hơn con trái hoặc con phải trên đường dẫn từ gốc đến chúng. Điều này hoạt động, nhưng bạn cần một đối số bổ sung để cho thấy rằng nó hoạt động. Cụ thể, bạn cần sử dụng công thức . n n i = 0n j = 0 ( i + jnnΣTôi= =0nΣj= =0n(Tôi+jTôi)= =(2n+2n+1)-1
Peter Shor

2
Chúng tôi muốn tìm tất cả các chuỗi nhị phân với chính xác 0 và 1. Chúng tôi đi qua cây nhị phân trong đó mỗi nút là một chuỗi nhiều nhất là 0 và 1. Chúng tôi không cần phải truy cập bất kỳ nút nào có nhiều hơn 0 hoặc hơn 1. Có bao nhiêu nút chúng ta cần phải truy cập? Có chuỗi với 0's và 1's. Tổng kết điều này trên tất cả cho . Bây giờ, chúng ta cần truy cập từng nút này với chi phí trung bình không đổi trên mỗi nút. Chúng ta có thể làm điều này bằng cách đến thăm từng đứa trẻ bên trái trước, và mỗi đứa trẻ bên phải thứ hai.n 2 n n n ( i + jnn2nnn iji,jnΣ n i = 0 Σ n j = 0 ( i + j(Tôi+jTôi)TôijTôi,jnΣTôi= =0nΣj= =0n(Tôi+jTôi)= =(2n+2n+1)-1
Peter Shor

2

Có lẽ tôi dày, nhưng câu hỏi ban đầu đã hỏi cách tạo ra tất cả các chuỗi nhị phân "cân bằng" có độ dài 2n hiệu quả hơn so với việc vượt qua một cây trong tất cả các chuỗi nhị phân có độ dài 2n và chỉ xuất ra những chuỗi được cân bằng. Vậy tại sao lại sử dụng một cây?

Đây là mã giả cho một thuật toán đệ quy tạo ra tất cả các chuỗi như vậy (từ khóa "suất" gửi một chuỗi đến đầu ra):

function all-balanced(n) {
  all-specified( "", n, n );
};

function all-specified( currentString, zeroes, ones ) {

  if (zeroes == 0) {
    for i = 0 to ones {
      currentString += "1";
    };
    yield currentString;
    return;
  };

  if (ones == 0) {
    for i = 0 to zeroes {
      currentString += "0";
    };
    yield currentString;
    return;
  };

  all-specified( currentString+"0", zeroes-1, ones );
  all-specified( currentString+"1", zeroes, ones-1 );
  return;
};

Nếu tôi hiểu nhầm điều gì đó, xin vui lòng cho tôi biết, nhưng dường như đây là câu trả lời hiệu quả nhất cho vấn đề thực sự được đặt ra, điều này không bao giờ chỉ định việc sử dụng cây.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.