![](/img/trans.png)
[英]Time complexity difference in Linkedlist implementation (Iterative VS Recursive)?
[英]Time complexity on iterative and recursive solution
我覺得我已經給了很多想法,嘗試了很多東西。 我設法解決了這個問題,並產生了正確的值,但是問題是時間效率不夠高。 它完成了Kattis測試中的2個,但由於超過了1秒的時間限制而未能完成3個測試。 恐怕我沒有辦法看到他們測試的輸入是什么。
我從一個遞歸解決方案開始,並完成了這一過程。 但是后來我意識到這不夠省時,因此我嘗試改用迭代解決方案。
我從讀取輸入開始,然后將其添加到ArrayList中。 然后,我將目標為1000的以下方法調用。
public static int getCorrectWeight(List<Integer> platesArr, int target) {
/* Creates two lists, one for storing completed values after each iteration,
one for storing new values during iteration. */
List<Integer> vals = new ArrayList<>();
List<Integer> newVals = new ArrayList<>();
// Inserts 0 as a first value so that we can start the first iteration.
int best = 0;
vals.add(best);
for(int i=0; i < platesArr.size(); i++) {
for(int j=0; j < vals.size(); j++) {
int newVal = vals.get(j) + platesArr.get(i);
if (newVal <= target) {
newVals.add(newVal);
if (newVal > best) {
best = newVal;
}
} else if ((Math.abs(target-newVal) < Math.abs(target-best)) || (Math.abs(target-newVal) == Math.abs(target-best) && newVal > best)) {
best = newVal;
}
}
vals.addAll(newVals);
}
return best;
}
我的問題是,對於減少大量數據,我是否可以通過某種方法來減少時間復雜度?
主要的問題是大小vals
和newVals
可以非常快速地增長,因為每個迭代可以增加一倍它們的大小。 您只需要存儲1000個左右的值即可管理。 您在限制值,但是因為它們存儲在ArrayList
,所以最終會有很多重復的值。
相反,如果您使用了HashSet
,那么它將HashSet
提高效率。
您僅需要存儲大小為2001(0到2000)的DP表,讓dp[i]
表示是否可以形成i
kg的權重。 如果權重超出數組范圍,請忽略它。 例如:
dp[0] = 1;
for (int i = 0; i < values.size(); i++){
for (int j = 2000; j >= values[i]; j--){
dp[j] = max(dp[j],dp[j-values[i]);
}
}
在這里, values
是存儲所有原始權重的位置。 除dp[0]
外,所有dp
值均應設置為0。
然后,檢查是否有可能達到1000。 如果不是,請檢查999和1001,依此類推。 這應該以O(1000n + 2000)
時間運行,因為n
最多為1000,所以應該及時運行。
順便說一句,這是一種改進的背包算法,您可能需要查找其他一些變體。
如果您對這種類型的問題過於籠統,則可能會認為您必須檢查所有可能的輸入組合(每個權重都可以包括或排除),為您提供2 n種組合以測試是否有n種輸入。 但是,這不是重點。 相反,這里的關鍵是所有權重都是整數,目標是1000。
讓我們先檢查極端情況,因為這限制了搜索空間。
如果所有權重均> = 1000,則選擇最小的權重。
如果至少有一個權重<1000,則總是比任何權重> = 2000更好,因此出於組合目的,您可以忽略任何權重> = 1000。
然后,應用動態編程。 保留前k個輸入的所有組合的集合(從其他海報中獲得HashSet作為建議,但BitSet更好,因為其最大值很小),並通過將所有先前的解決方案與k + 1組合來增加k的輸入。
考慮完所有可能性后,只需搜索位向量以獲得最佳響應。
static int count() {
int[] weights = new int[]{900, 500, 498, 4};
// Check for corner case to limit search later
int min = Integer.MAX_VALUE;
for (int weight : weights) min = Math.min(min, weight);
if (min >= 1000) {
return min;
}
// Get all interesting combinations
BitSet combos = new BitSet();
for (int weight : weights) {
if (weight < 1000) {
for (int t = combos.previousSetBit(2000 - weight) ; t >= 0; t = combos.previousSetBit(t-1)) {
combos.set(weight + t);
}
combos.set(weight);
}
}
// Pick best combo
for (int distance = 0; distance <= 1000; distance++) {
if (combos.get(1000 + distance)) {
return 1000 + distance;
}
if (combos.get(1000 - distance)) {
return 1000 - distance;
}
}
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.