Làm thế nào để tìm tập hợp tối đa các phần tử


14

Tôi có một vấn đề thuật toán.

TnSTaSa|S|

Ví dụ:

  1. Nếu = [1, 3, 4, 1, 3, 6], thì có thể là [3, 3, 6] hoặc [3, 4, 6] hoặc [4, 3, 6].TS
  2. Trong = [7, 5, 1, 1, 7, 4], thì là [7, 5, 7, 4].TS

Tôi đã thử chức năng đệ quy này.

function(T):
    if minimum(T) >= length(T): 
        return T
    else: 
        return function(T\minimum(T))

Có bất kỳ thuật toán không đệ quy. (Tôi đã không kiểm tra thuật toán đệ quy của mình, vì vậy nó có thể có một số lỗ hổng.)

Câu trả lời:


14

Sắp xếp T. Sau đó lấy các phần tử trong khi T[i] >= i+1.

Ví dụ sorted(T)=[6,4,3,3,1,1]. Sau đó, T[0] = 6 > 1, T[1] = 4 > 2, T[2] = 3 <= 3và cuối cùng, T[3] = 3 < 4vì vậy chúng tôi có S = [T[0], T[1], T[2]].


3
Điều này, tất nhiên, bỏ lỡ giải pháp khác , nhưng có vẻ như OP đang tìm kiếm bất kỳ giải pháp nào , hơn là tất cả các giải pháp. {6,3,3}
Rick Decker

2
Nó có được số lượng các yếu tố đúng. Chúng tôi biết chúng tôi có giải pháp với 3 yếu tố nhưng không phải với 4; trong trường hợp này, chúng tôi có 4 yếu tố ≥ 3, vì vậy chúng tôi biết rằng chúng tôi có thể chọn bất kỳ 3 yếu tố nào cho giải pháp.
gnasher729

3
Tôi đánh giá cao một lập luận của sự đúng đắn.
Raphael

Tôi nghĩ rằng bạn có thể làm điều đó trong thời gian O (n) với một biến thể của introselect.
user2357112 hỗ trợ Monica

8

Từ nhận xét ban đầu của tôi: Điều này liên quan chặt chẽ đến một số lượng phổ biến trong đánh giá năng suất học tập, chỉ số Hirsh, được gọi là -indexh . Nói tóm lại, nó được định nghĩa là số lượng ấn phẩm người ta có sao cho mỗi trong số họ có ít nhất h trích dẫn ( h lớn nhất như vậy ).hhh

Cách duy nhất để vấn đề của bạn khác biệt là bạn sẽ quan tâm không chỉ về việc có bao nhiêu ấn phẩm thỏa mãn tiêu chí mà còn cả số lượng trích dẫn của chúng , nhưng đó là một sửa đổi nhỏ. Dữ liệu đã có, thuật toán ban đầu chỉ cần bỏ nó.

Tính toán được thực hiện nói chung khá đơn giản và đồng ý với câu trả lời của Karolis Juodelė .

Cập nhật: Tùy thuộc vào kích thước và đặc tính của dữ liệu của bạn, có thể đáng để khám phá các phương pháp sắp xếp một phần mảng bằng cách lọc dữ liệu ở trên và dưới điểm then chốt (quicksort xuất hiện trong tâm trí). Sau đó, tùy thuộc vào việc có quá ít hay quá nhiều điều chỉnh trục và làm lại trên tập hợp con có chứa nó hay không. Bạn không cần một trật tự giữa các yếu tố cao hơn và chắc chắn không phải giữa các yếu tố thấp hơn thế. Vì vậy, ví dụ, khi bạn tìm thấy tất cả các phần tử lớn hơn hoặc bằng h 1 và có ít hơn h 1 trong số chúng, bạn không cần phải chạm vào tập hợp con đó một lần nữa, chỉ cần thêm vào nó. Điều này chuyển đổi đệ quy vốn có thành quicksort thành đệ quy đuôi và do đó có thể được viết lại thành một vòng lặp.hh1h1

Haskell của tôi hơi gỉ nhưng điều này sẽ làm những gì tôi mô tả ở trên và dường như hoạt động. Hy vọng nó có thể được hiểu ở một mức độ nào đó, tôi rất vui khi được giải thích thêm.

-- just a utility function
merge :: [a] -> [a] -> [a]
merge [] ys = ys
merge (x:xs) ys = x : merge xs ys

-- the actual implementation
topImpl :: [Int] -> [Int] -> [Int]
topImpl [] granted = granted
topImpl (x:xs) granted
  | x == (1 + lGreater + lGranted) = x : merge greater granted
  | x > (1 + lGreater + lGranted) = topImpl smaller (x : merge greater granted)
  | otherwise = topImpl greater granted
  where smaller = [y | y <- xs, y < x]
        greater = [y | y <- xs, y >= x]
        lGreater = length greater
        lGranted = length granted

-- starting point is: top of whole array, granted is empty
top :: [Int] -> [Int]
top arr = topImpl arr []

Ý tưởng là thu thập grantednhững gì bạn biết chắc chắn sẽ tham gia vào kết quả, và không sắp xếp nó thêm nữa. Nếu greatercùng với sự xphù hợp, chúng ta may mắn, nếu không, chúng ta cần thử với một tập hợp nhỏ hơn. (Các trục xchỉ đơn giản là bất cứ điều gì đã xảy ra là mục đầu tiên của sublist rằng hiện đang xem xét.) Lưu ý rằng lợi thế đáng kể so với dùng các yếu tố lớn nhất từng người một là chúng ta làm điều này trên các khối kích thước trung bình và không cần sắp xếp chúng thêm.remmộtTôinTôing/2

Thí dụ:

Hãy lấy bộ của bạn [1,3,4,1,3,6].

  1. x = 1, granted = [], greater = [3,4,1,3,6]. Ouch, chúng tôi đã gặp một trường hợp bệnh lý khi trục quá nhỏ (thực sự quá nhỏ mà smallertrống) ngay trong bước đầu tiên. May mắn là algo của chúng tôi đã sẵn sàng cho điều đó. Nó loại bỏ xvà thử lại với greatermột mình.

  2. x = 3, granted = [], greater = [4,3,6]. Cùng nhau, chúng tạo thành một mảng có độ dài 4 nhưng chúng ta chỉ có giới hạn từ bên dưới 3 nên quá nhiều. Lặp lại greatermột mình.

  3. x = 4, granted = [], greater = [6]. Điều này cung cấp cho một mảng gồm 2 phần tử 4 mỗi phần, dường như chúng ta có thể đã sử dụng cho một số phần tử nữa. Giữ cái này và lặp lại smaller = [3].

  4. x = 3, granted = [4,6], greater = []. Điều này cùng nhau cung cấp một mảng gồm 3 phần tử ≥ 3 mỗi phần, vì vậy chúng tôi có giải pháp của chúng tôi [3,4,6]và chúng tôi có thể quay lại. (Lưu ý rằng hoán vị có thể thay đổi tùy theo thứ tự đầu vào, nhưng sẽ luôn chứa các điều khoản cao nhất có thể, không bao giờ [3,3,6]hoặc [3,3,4]cho ví dụ của bạn.)

(Btw. Lưu ý rằng sự đệ quy thực sự đã sụp đổ theo một chu kỳ.) Sự phức tạp có phần tốt hơn so với quicksort vì có nhiều so sánh được lưu:

Trường hợp tốt nhất (ví dụ [2,2,1,1,1,1]): một bước so sánh , n-1

Trường hợp trung bình: bước, so sánh O ( n ) trong tổng sốÔi(đăng nhậpn)Ôi(n)

nÔi(n2)

Có một vài so sánh không cần thiết trong đoạn mã trên, như tính toán smallerxem chúng ta có cần nó hay không, chúng có thể được gỡ bỏ dễ dàng. (Tôi nghĩ rằng đánh giá lười biếng sẽ quan tâm đến điều đó mặc dù.)


6

Không có gì sai với thuật toán của bạn và tất nhiên hầu hết các thuật toán đệ quy có thể được chuyển đổi thành các vòng lặp, ở đây là phiên bản vòng lặp của mã đệ quy của bạn:

function(T):
    while minimum(T) <= lenght(T):
         remove minimum(T) from T
    loop

6
Tất cả các thuật toán đệ quy có thể được chuyển đổi thành các vòng lặp. Rốt cuộc, một máy Turing không biết gì về đệ quy.
David Richerby

4

Bất kỳ thuật toán đệ quy có thể được viết lại để sử dụng phép lặp. Rốt cuộc, một máy Turing không biết gì về đệ quy nhưng có thể thực hiện bất kỳ thuật toán nào. Về nguyên tắc, bạn có thể viết lại hàm đệ quy của mình bằng cách viết mã thao tác ngăn xếp của riêng bạn để ghi nhớ các giá trị của tham số của hàm và bất kỳ biến cục bộ nào mà nó có thể có. Trong trường hợp cụ thể này, chức năng của bạn là đệ quy đuôi (một khi cuộc gọi đệ quy trả về, điều được gọi là ngay lập tức cũng trả về), do đó bạn thậm chí không cần phải duy trì ngăn xếp.


3

Sử dụng một heap tối thiểu để thực hiện một heapsort một phần, vì bạn không cần toàn bộ mảng được sắp xếp.

Giữ các yếu tố popping tham lam cho đến khi bạn vượt quá ngưỡng cho trước.


2
Ngoài ra, tôi cũng đánh giá cao một ý tưởng về tính đúng đắn.
Raphael
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.