簡體   English   中英

查找總和小於 k 的最大元素

[英]Find maximum elements whose sum is less than k

這是我上周試過的一個 hackerrank 程序。 購物車中有一個項目列表,每個項目都有與之相關的成本。

n件物品, ith件物品的成本是i美元, m件物品已經被購買並在數組arr中表示。 目前,有k美元,求用這筆錢購買任意數量的物品后,總共可以擁有的不同物品的最大數量。

例子:

Consider n=10,m=3,k=10,arr=[1,3, 8]. 

因此,任務是找出除 {1,3,8} 項外,10 美元內可以購買 10 項不同項的最大數量。 除了給定的 3 件商品外,最多可以購買 2 件商品,假設商品 - 2 和商品 - 5。總成本=2+5=7,小於 10。

讓我們考慮三個項目 - Item - 2, Item - 4, 200,

答案是 5 (3 個已經購買,2 個剛剛購買)。

function 必須返回 integer,表示可以購買的不同項目的最大數量。

function 具有以下參數:

n : an integer denoting the number of items arr[m]: an integer array denoting already purchased items
k : an integer denoting amount in dollars Constraints

約束 -

1≤n≤10^6
1≤m≤10^5
1≤k≤10^9
1≤a[i]≤10^6

這個問題已經由某人發布在這里,以防萬一有人想查看確切的問題。

現在,我的思考過程。 因為我有 K 美元,所以我必須找到要收集的最大元素,其總和為 k。 我從 1 到 n 開始一個數字,並檢查輸入列表中是否缺少該數字,如果是,則添加到總和,並執行此過程直到總和小於或等於k

public int process(int n, int k, List<Integer> arr) {
    Set<Integer> set = new HashSet<>(arr);
    long sum = 0;
    int result = arr.size();
    for(int i=1; i<=n; i++) {
        if(set.contains(i) == false) {
            if(sum + i <= k) {
                sum += i;
                result++;
            }
        }   
    }
    return result;
}

現在,該程序適用於給定的示例測試用例。

其他一些測試用例是:

n=5, k=8, arr=[3,6] . Expected answer = 5

n=8, k=5, arr=[1,2] . Expected answer = 3

n=1, k=10, arr=[1] . Expected answer = 1

我的程序使用這些示例測試用例。 但是 hackerrank 還有 11 個其他隱藏的測試用例,它們都是隱藏的,但都失敗了,結果是錯誤的,我沒有看到任何 memory 錯誤或這些隱藏測試用例的超時錯誤。

現在我的問題是,解決這個問題的正確方法是什么? 正如問題所說,要找到要收集的最大元素,我從 1 到 n 開始尋找丟失的元素,這是有效的方法,但仍然失敗。

當您詢問正確的方法時,我不會發布完整的代碼,但會為您提供一些指導。 如果這不是一個好的答案,請隨時告訴我,我會刪除它。

  1. 查看約束,並驗證代碼中某處是否可能發生溢出
  2. 你的循環從1n 通常他們 go 從0n-1 ,也許某處off-by-one錯誤? 使用邊緣案例進行測試
  3. 您遍歷整個范圍[1..n] 是否存在可以提前停止的條件?
  4. 價格是按升序排列的,也許有一個計算總價的通用公式? 這可能意味着重新考慮整個算法,但您會獲得很多時間。

我在您的代碼中沒有看到任何明顯的錯誤。 對於失敗的案例(我推斷有大量數據輸入),您是否可能犯了輸入錯誤? 就溢出的可能性而言,一個int可以容納的最大值是2,147,483,647。 從問題描述來看,一個int應該足夠了,你不需要任何long變量。

無論如何,我會建議一些改變:

  1. 優化process內 for 循環中的退出條件,以在 for 循環中測試更大的i值無果時中斷。 這也導致了一個簡化的循環體。
  2. 稍微更改接口以進行process ,以便調用者只需傳遞一個Intger數組; 從此數組創建List<Integer>變量將由process完成。 為什么調用者應該從問題描述中知道需要創建一個List ,它指定只傳遞一個數組?
import java.util.*;

public class Test {
    public int process(int n, int k, Integer[] arr) {
        Set<Integer> set = new HashSet<Integer>(new ArrayList<Integer>(Arrays.asList(arr)));

        int sum = 0;
        int result = arr.length;
        // Never let i exceed n and once you have an i value
        // where the current sum + i exceeds k, you can stop:
        for (int i = 1; i <= n && sum + i <= k; i++) {
            if (!set.contains(i)) {
                sum += i;
                result++;
            }
        }
        return result;
    }

    public static void main(String[] args) {
        Test t = new Test();

        Integer[] arr = {1, 3, 8};
        System.out.println(t.process(10, 10, arr));
    }
}

印刷:

5

關鍵可能是短語“找到不同項目的最大數量”中的單詞distinct嗎? 如果數組包含重復項怎么辦? 嘗試初始化結果

int result = set.size();

相反,看看它是否解決了問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM