Làm thế nào để sử dụng thuật toán tham lam để tìm chuỗi không giảm gần nhất với chuỗi đã cho?


20

Bạn được cấp n số nguyên tất cả từ đến . Trong mỗi số nguyên bạn nên viết một số nguyên trong khoảng từ đến với yêu cầu rằng tạo thành một chuỗi không giảm. Xác định độ lệch của chuỗi như vậy là . Thiết kế một thuật toán tìm các b_i với độ lệch tối thiểu trong thời gian chạy O (n \ sqrt [4] {l}) . 0 l một i b i 0 l b i max ( | một 1 - b 1 | , ... , | một n - b n | ) b i O ( n 4 a1,,an0laibi0lbimax(|a1b1|,,|anbn|)biO(nl4)

Tôi thực sự không có manh mối nào để bắt đầu giải quyết câu hỏi này. Nó trông giống như một câu hỏi lập trình động đối với tôi, nhưng giáo sư nói rằng điều này nên được giải quyết bằng thuật toán tham lam. Sẽ rất được đánh giá cao nếu ai đó có thể chỉ cho tôi đi đúng hướng bằng cách đưa ra một gợi ý nhỏ.

Câu trả lời:


9

Hãy bắt đầu với quan sát sau:

Đặt biểu thị mức tối đa của chuỗi và để biểu thị mức tối thiểu của chuỗi . Nếu , thì chọn là tối ưu.a 1 , . . . , a n m i n a 1 = m a x b 1 = b 2 = . . . = B n = ( m một x + m i n ) / 2 maxa1,...,anmina1=maxb1=b2=...=bn=(max+min)/2

Tại sao điều này là trường hợp? Chà, vì chuỗi bắt đầu với mức tối đa, chúng tôi chọn b1 lớn và chịu độ lệch lớn so với mức tối thiểu của chuỗi (vì bất kỳ b_i tiếp theo nào bicũng phải lớn hơn hoặc bằng b1 ), hoặc chúng tôi chọn b1 nhỏ và chịu đựng độ lệch để max . Trung bình giảm thiểu độ lệch tối đa.

Bây giờ chúng ta có thể cố gắng khái quát hóa quan sát này để sử dụng trên các chuỗi chung a1,...,an . Chẳng hạn, chúng ta có thể phân vùng bất kỳ chuỗi nào thành các chuỗi con, sao cho mỗi chuỗi bắt đầu với mức tối đa của chuỗi con tương ứng.

Ví dụ: được phân chia thành , và .( 2 ) ( 6 , 4 , 1 , 5 , 2 ) ( 8 , 7 , 5 , 1 )(2,6,4,1,5,2,8,7,5,1)(2)(6,4,1,5,2)(8,7,5,1)

Với phân vùng này, giờ đây chúng ta có thể giải quyết riêng từng chuỗi này và nhận được sự phân công của , tuy nhiên có thể vi phạm điều kiện không giảm. Điều này có thể được sửa chữa mà không mất đi sự tối ưu.bi

Quan sát rằng chuỗi con cuối cùng luôn chứa tối đa tối của toàn bộ chuỗi (nếu không, sẽ có một chuỗi con khác sau chuỗi đó). Đặt là các giá trị chúng ta đã gán cho các chuỗi con . Bây giờ, để đạt được mức độ không giảm trong , chúng tôi bắt đầu từ phía sau tại và tiến lên phía trước. Nếu lớn hơn , chúng ta chỉ cần đặt . Nếu nó nhỏ hơn, chúng tôi giữ nó. Sau đó, chúng tôi tiến hành so sánh với , v.v. Lưu ý rằng việc hạ bất kỳ nào xuống giá trị củaw 1 , w 2 , . . . , w k k w 1 , . . . , w k w k w k - 1 w kmaxw1,w2,...,wkkw1,...,wkwkwk1wkwk1:=wkwk2wk1wiwi+1không bao giờ tăng độ lệch, vì giá trị maximium trong chuỗi con được gán với luôn luôn thấp hơn mức tối đa trong chuỗi con được gán với .wiwi+1

Thuật toán này nên chính xác, tôi nghĩ. Liên quan đến thời gian chạy, bước quan trọng là tính toán cực đại ngày càng tăng cho các chuỗi con, điều này có thể xảy ra trong không? Không chắc chắn nơi đóng góp.O(n)l


2

Tôi sẽ nghĩ lớn ở đây chỉ làm việc thông qua các gợi ý bạn đã đưa ra. Hãy đi đến gợi ý ban đầu để nói rằng là thứ bạn nên thử trước tiên. Tôi có thể nghĩ về một thuật toán tham lam có thời gian đó.O(nl)

Phần của độ phức tạp thời gian có nghĩa là bạn có thể giữ một danh sách đếm số lần xuất hiện của mỗi giá trị 0 .. l . Đó là, chỉ cần tạo một tập hợp Count = C 0 , Mạnh , C l để theo dõi số lượng của mỗi l trong tập hợp. Bạn có thể tạo danh sách initalize bằng cách quét chuỗi đầu vào một lần.l0..lCount=C0,,Cll

Bạn có thể quét danh sách này trong để nhận giá trị tối đa và tối thiểu. Nếu bạn điền vào toàn bộ danh sách b với điểm giữa này, phương sai của bạn chỉ đơn giản là sự khác biệt so với giá trị này và tối đa / phút. Về cơ bản đây là trường hợp xấu nhất của bạn, hãy gọi nó là b w .O(l)bbw

Vì vậy, làm việc theo cách của bạn để từ bên trái. Bạn vừa có thể thả elemeent này từ Đếm và nhận được min / max của b [ i + 1 ] ... b [ n ] trong O ( l ) . Bây giờ chúng ta có thể tham lam. Chúng tôi không chọn b i > b w vì điều đó buộc toàn bộ danh sách còn lại (để đáp ứng yêu cầu không giảm) và do đó làm tăng phương sai. Giá trị tối thiểu chúng ta có thể chọn là b [ i - 1 ] . Nếu một tôibiCountb[i+1]b[n]O(l)bi>bwb[i1]ailà trong phạm vi chấp nhận được, chúng tôi chọn nó, nếu dưới phạm vi hơn mức sử dụng tối thiểu. Điều này giảm thiểu phương sai tại với các ràng buộc đã biết.bi

Đây chỉ là một ý tưởng, có lẽ tôi may mắn và nó chỉ cho bạn đi đúng hướng. Thuật toán này có thể không hoạt động (nó thực hiện cho một vài thử nghiệm đơn giản của tôi), nhưng nó phù hợp với các gợi ý được đưa ra, vì vậy có lẽ nó hữu ích. Nếu đúng, có thể dễ dàng thấy rằng phần chắc chắn có thể được thả xuống O ( log l ) , thậm chí xa hơn nữa, tôi không chắc chắn.O(l)O(logl)


2

Đây là giải pháp của giáo sư, ông gọi là "giảm": Với mỗi từ 0 đến l , hãy thử xây dựng một giải pháp nếu chúng ta biết rằng độ lệch nhỏ hơn hoặc bằng i . I đầu tiên mà một giải pháp có thể được tìm thấy là độ lệch tối thiểu. Chúng ta có thể tìm thấy một giải pháp cho độ lệch trong thời gian O ( n ) . Vì vậy thời gian chạy là O ( n l ) . Sau đó, thay vì sử dụng tìm kiếm tuyến tính, chúng ta có thể sử dụng tìm kiếm nhị phân để xác định độ lệch nhỏ nhất mà giải pháp có thể thực hiện được. Điều này giúp giảm thời gian chạy xuống O ( n log li0liiO(n)O(nl) , Trong đó đáp ứng các yêu cầu của O ( n 4 O(nlogl).O(nl4)


4
Vì vậy, các là một mánh khóe ... Nhưng tôi bị thu hút nhiều hơn bởi "Chúng ta có thể tìm ra giải pháp cho độ lệch trong thời gian O (n)" .. đókhông phảilà phần thú vị? O(nl4)
jmad

@jmad Với , đối với mỗi j , lấy b j là giá trị thấp nhất là ít nhất là lớn như tất cả trước b k , và đó là không nhiều hơn tôi xa một j . Nếu chúng ta không thể tìm thấy một giá trị như vậy, nó có nghĩa là gì? Nó có nghĩa là một trước b t là hơn tôi lớn hơn một j . Vì vậy, một trước một t là hơn 2 i lớn hơn một j . Vì vậy, giá trị của tôi là không thể. Nếu bạn vượt qua được nijbjbkiajbtiajat2iajinCác giá trị mà không bị kẹt như thế này, bạn đã tìm thấy giải pháp cho mà không cần quay lại, trong thời gian O ( n ) . iO(n)
jwg

O (n log l) sẽ là một gợi ý mạnh mẽ rằng bạn cần thực hiện một số tìm kiếm nhị phân trong phạm vi từ 0 đến l.
gnasher729

0

Tôi nghĩ rằng điều này nên được thực hiện trong O (n).

Lấy bài toán tương tự: Cho , 1 ≤ i ≤ n và d ≥ 0, tìm b i theo thứ tự không giảm dần sao cho | a i - b i | For d cho tất cả tôi, hoặc cho thấy rằng điều đó là không thể. Điều này có thể được thực hiện trong O (n) và sử dụng tìm kiếm nhị phân, vấn đề ban đầu được giải quyết trong O (n log l).aibi|aibi|d

Bây giờ nếu có i ≤ j mà a_i - a_j> 2d, thì không có giải pháp (vì ).biaid,bjaj+d<ai2d+d=aidbi

Nhưng nếu a_i - a_j 2d cho tất cả i ≤ j thì tôi nghĩ một giải pháp sẽ luôn được tìm thấy. Vì vậy, tất cả những gì chúng ta phải làm là tìm m = max (a_i - a_j) cho tất cả i ≤ j và chọn d = floor ((m + 1) / 2). Mức tối đa đó có thể được tìm thấy trong O (n).


Ý tưởng hấp dẫn! Tôi có thể tin rằng một cái gì đó như thế này có thể hoạt động, nhưng có vẻ như có một khoảng cách lớn ở cuối câu trả lời của bạn và tôi đang gặp khó khăn trong việc điền vào các chi tiết. Bạn có một bằng chứng rằng nếu cho tất cả i j thì một giải pháp luôn tồn tại? Quan trọng hơn, làm thế nào để chúng ta tìm thấy nó? Câu hỏi ban đầu nói rằng chúng ta phải tìm b i 's. Ngay cả khi chúng tôi giả sử có một giải pháp tồn tại, tôi vẫn gặp khó khăn trong việc tìm cách tìm ra b i tương ứng . bạn có thể giải thích về điều đó không? aiaj2dijbibi
DW
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.