[英]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.