实现双指针方法时堆缓冲区溢出



我正在解决这个脑筋急转弯

给定一个已排序的1索引整数数组非递减顺序,找到两个数字,使它们加起来为具体目标数量。设这两个数字为数字[index1]数字[index2],其中1<=index1<index2<=数字.长度.

返回index1和index2这两个数字加一后的索引作为长度为2的整数数组[index1、index2]。

生成测试时,正好有一个解决方案。你可以不使用同一元素两次。

您的解决方案只能使用恒定的额外空间。

示例1:

Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. 
Therefore, index1 = 1, index2 = 2. 
We return [1, 2].

我的解决方案是给出这个错误:

=================================================================
==31==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000620 at pc 0x000000345e97 bp 0x7ffcd6847990 sp 0x7ffcd6847988
READ of size 4 at 0x602000000620 thread T0
#2 0x7f2c3b9790b2  (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
0x602000000620 is located 0 bytes to the right of 16-byte region [0x602000000610,0x602000000620)

我做了一些研究,发现这通常是由于调用的索引太远(即在您使用的数据结构范围之外(造成的,但由于我使用的是向量,我不明白为什么会出现这种错误。它发生在以下测试用例中:[5,25,75]100.

class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
// can have an i that points forward and a j that loops through everything until sum
// is greater
// checking recursively
// if sum greater stop checking (as list is increasing)
// can reset i each time??
// add 1 at the end

vector<int> indices;
int i = 0;
int j = 0;

// for loop on top?
for (int i; i < numbers.size(); i++)
int j = 0;
while (numbers[i] + numbers[j] <= target) {
if (numbers[i] + numbers[j] == target && i != j) {
// some if determining if i or j is greater
// to determine the order in which to push back
indices.push_back(i+1);
indices.push_back(j+1);
return indices;
} else {
j++;
}
}
return indices;
}
};

其他测试都通过了,但这次没有通过。我试图在这里使用两个指针的方法。

这段代码有几个问题,一些简单的语法错误,一些算法问题。

首先,正如其他人所提到的,i在外部for循环中未初始化。幸运的是,这永远不会发挥作用,因为你没有环体周围的支架。你的代码等同于

for (int i; i < numbers.size(); i++) {
int j = 0;
}
while (numbers[i] + numbers[j] <= target) {
// ...
}

这可能不是您想要的,所以您需要初始化i并在循环体周围添加{}

for (int i = 0; i < numbers.size(); i++) {
int j = 0;
while (numbers[i] + numbers[j] <= target) {
// ...
}
}

当然,在循环之外也不需要ij的冗余定义。这些变量会被循环中定义的变量隐藏起来,并且永远不会被使用。


当然,这仍然不能解决超出范围的错误。为此,您需要重新思考您的算法。让我们浏览一下,找出问题所在。我只关注内部while循环。

假设,从您的测试用例中,numbers = {5, 25, 75}target = 100

第一次迭代:

  • i = 0j = 0
  • numbers[i] + numbers[j]->numbers[0] + numbers[0]-&gt-&gt;5 + 5->10。这小于100,因此进入循环
  • if (10 == 100)false,因此选择了else分支
  • j++,所以现在i = 0j = 1

第二次迭代:

  • numbers[i] + numbers[j]->numbers[0] + numbers[1]->5 + 25->CCD_ 26。这小于100,所以循环继续
  • if (30 == 100)false,因此选择了else分支
  • j++,所以现在i = 0j = 2

第三次迭代:

  • numbers[i] + numbers[j]->numbers[0] + numbers[2]->CCD_ 36->80。这小于100,所以循环继续
  • if (80 == 100)false,因此选择了else分支
  • j++,所以现在i = 0j = 3

第三次迭代:

  • numbers[i] + numbers[j]->numbers[0] + numbers[3]->吊杆

j现在超出了numbers的有效索引范围,因此当您尝试访问numbers[j]时,程序的行为将变得未定义。在这种情况下,它崩溃了;最好的结果。

正如上述评论所指出的,

for (int i; i < numbers.size(); i++)

此处"int i"隐藏"int i=0;"的上一个本地声明(C4456(,这是不希望的。

问题是,尽管i被绑定到范围[0,n-1],但j不是,当j超过范围时,这可能导致访问违规。

您可以使用下面的代码,这些代码将通过您的所有测试用例。

class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//first we will declare an additional vector which will return desired solution
vector<int> mult;
//by using two pointer approach
for(int i = 0; i<=nums.size(); i++){
for(int j = i+1; j<nums.size();j++){
//checking for condition
if(nums[i]+nums[j]==target){
mult.push_back(i);
mult.push_back(j);
j++;
return mult;
}

}


}
return mult;
}
};

相关内容

  • 没有找到相关文章

最新更新