c++ - 向量下标超出函数范围
问题描述
我为这个背包函数使用了一个二维向量,它不断返回超出范围的向量(第 1733 行),但向量不应该超过它们的大小并导致溢出。将 for 循环更改为 < 而不是 <= 无效。
int knapsack(int cap, vector<int>& weight, vector<int>& value, int n)
{
vector<vector<int>> K;
K.resize(cap, vector<int>(n));
int i = 0;
int j = 0;
for (i = 0; i <= n; i++)
{
for (j = 0; j <= cap; j++)
{
if (i == 0 || j == 0)
K[i][j] = 0;
else if (weight[i - 1] <= j)
{
K[i][j] = max(weight[i - 1] + K[i - 1][j - weight[i - 1]], K[i - 1][j]);
}
else
{
K[i][j] = K[i-1][j];
}
}
}
return K[i][j];
}
根据我所读到的内容,调整大小将是解决方案,但我已经使用向量大小的适当变量来做到这一点。还是我需要使用回推?
解决方案
矢量索引
当您声明K
如下:
vector<vector<int>> K;
K.resize(cap, vector<int>(n));
然后向量K
有长度cap
,每个向量K[i]
都有长度n
。但是,在您的 for 循环中,我看到:
for (i = 0; i <= n; i++)
{
for (j = 0; j <= cap; j++)
{
if (i == 0 || j == 0)
K[i][j] = 0;
...
}
}
看起来索引的顺序在这里是错误的,因为在if
-statement 中,您可以设置K[n][0]
或K[0][cap - 1]
,当唯一有效的最大索引是K[cap - 1][0]
andK[0][n - 1]
时。
使用push_back()
更安全。在这种情况下,不要忘记预留空间以避免不必要的重新分配。
循环范围
正如评论中其他人所提到的,在迭代n
元素时,正确的写法是:
for (i = 0; i < cap; ++i)
所以没有'<= n',因为它会访问'cap + 1'th元素。
在循环之后,迭代器将指向循环结束之外
一旦完成类似循环for (i = 0; i < cap; ++i)
,它将增加到i
value cap
。所以最后一行:
return K[i][j];
肯定会访问超出范围的向量。你应该写这样的东西:
return K[cap - 1][n - 1];
或者,您可以使用成员函数back()
访问向量的最后一个元素,并编写:
return K.back().back();
未使用的函数参数
为什么value
在这个函数中根本没有使用一个参数?
断言weight
具有正确的大小
访问超出范围的向量的另一个可能来源可能是该向量weight
的大小不正确。您可以在代码中添加一个assert()
以在调试版本中捕获此错误:
#include <cassert>
...
int knapsack(int cap, vector<int>& weight, vector<int>& value, int n)
{
assert(weight.size() >= n - 1);
...
推荐阅读
- c# - 使用 selenium C# 处理打印弹出窗口
- android - 在 Android 10 (Q) 上拍摄和裁剪图像后,Google Photo App 崩溃
- python - 如何打印特定的numpy数组对
- c - C中的矩阵指针
- python - 将 VS Code 和 miniconda 用于 python 笔记本的问题
- python - 有没有办法检测图像中是否存在过滤器?
- javascript - 保持两个客户端之间的通信,即使它们的 IP 地址发生变化
- python - 从 JSON 嵌套数组中获取数据并放入 excel
- python - Python 附加到预定义的列表列表(这里发生了什么?)
- validation - govalidator ValidateMap 验证数组的映射