-1

I'm solving this brain teaser

Given a 1-indexed array of integers numbers that is already sorted in non-decreasing order, find two numbers such that they add up to a specific target number. Let these two numbers be numbers[index1] and numbers[index2] where 1 <= index1 < index2 <= numbers.length.

Return the indices of the two numbers, index1 and index2, added by one as an integer array [index1, index2] of length 2.

The tests are generated such that there is exactly one solution. You may not use the same element twice.

Your solution must use only constant extra space.

Example 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].

and my solution is giving this error:

=================================================================
==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)

I did some research and saw that this is usually caused by calling an index that's too far (i.e. outside the range of the data structure you're using) but since I'm using vectors I don't get why I have this error. It happened on the following test case: [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;
    }
};

The other tests are passing but this one is failing. I am trying to use a two-pointer approach here.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
Battleship
  • 11
  • 3
  • Welcome to Stack Overflow. Please read the [About](http://stackoverflow.com/tour) page soon and also visit the links describing [How to Ask a Question](http://stackoverflow.com/questions/how-to-ask) and [How to create a Minimal Reproducable Example](https://stackoverflow.com/help/minimal-reproducible-example). Providing the necessary details, including your MRE, compiler warnings and associated errors, and sample data if any, will allow everyone here to help you with your question. Your error is likely the result of something happending elsewhere in your code. – David C. Rankin Aug 24 '22 at 02:20
  • 3
    `i` is uninitialized in this for loop `for (int i; i < numbers.size(); i++)`. – Aamir Aug 24 '22 at 02:27
  • *"since I'm using vectors"* -- use of vectors does not make code immune to using an index that is too large. (Vectors do, however, give you the option to use `at()` instead of `operator[]`, which would give you bounds checking.) – JaMiT Aug 24 '22 at 02:27
  • From the error `"READ of size 4"` (you are attempting to read an `int` value) `"0 bytes to the right of 16-byte region ..."` after the end of some 16-byte block of memory. From the description `numbers = [2,7,11,15]` would be a 16-byte array (4 - `int`) and `"0 bytes to the right ..."` would suggest you index 1-past the end. So either `i` or `j` is going out of bounds. – David C. Rankin Aug 24 '22 at 02:28
  • `for (int i; ...` Good eyes @Aamir ! Make`for (; i < numbers.size(); i++)` – David C. Rankin Aug 24 '22 at 02:28
  • @Aamir *"`i` is uninitialized in this for loop"* -- true, but not the direct problem, as that loop consists of `int j = 0;` (there are no braces so the body is just that one line -- not good eyes, I [enabled warnings](https://stackoverflow.com/questions/57842756/why-should-i-always-enable-compiler-warnings)). – JaMiT Aug 24 '22 at 02:32
  • I think the next course of action should be to provide a better reason why your indices cannot go out of bounds than "I'm using vectors". What causes the loop `while (numbers[i] + numbers[j] <= target)` to end when `i` is `0`? – JaMiT Aug 24 '22 at 02:41
  • Two notes: 1) Since the values are sorted, you can start the inner loop from `i + 1` (assuming the other issues are fixed) and terminate when `numbers[i] + numbers[j] > target`. 2) If there is test data with thousands of values, a binary search from `i + 1` to `min(size(), i + target - numbers[i])` for `target - numbers[i]` would on average be quicker than linear search. – Ken Y-N Aug 24 '22 at 04:19

3 Answers3

1

There are several issues with this code, some simple syntactic mistakes, some algorithmic problems.

First, as others have mentioned, i is uninitialized in your outer for loop. Luckily, that never comes into play because you have no braces around the loop body. Your code is equivilent to

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

This is presumably not what you intended, so you need to both initialize i and add {} around the loop body:

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

Of course, you also don't need the redundant definitions of i and j outside the loops. Those variables get hidden by the ones defined within the loops, and are never used.


Of course, this still doesn't address your out-of-range error. For that, you need to re-think your algorithm. Lets walk through it to find the issue. I'll just focus on the inner while loop.

Assuming, from your test case that numbers = {5, 25, 75} and target = 100.

First iteration:

  • i = 0 and j = 0
  • numbers[i] + numbers[j] -> numbers[0] + numbers[0] -> -> 5 + 5 -> 10. That's less than 100, so the loop is entered
  • if (10 == 100) is false, so the else branch is selected
  • j++, so now i = 0 and j = 1

Second iteration:

  • numbers[i] + numbers[j] -> numbers[0] + numbers[1] -> 5 + 25 -> 30. That's less than 100, so the loop continues
  • if (30 == 100) is false, so the else branch is selected
  • j++, so now i = 0 and j = 2

Third iteration:

  • numbers[i] + numbers[j] -> numbers[0] + numbers[2] -> 5 + 75 -> 80. That's less than 100, so the loop continues
  • if (80 == 100) is false, so the else branch is selected
  • j++, so now i = 0 and j = 3

Third iteration:

  • numbers[i] + numbers[j] -> numbers[0] + numbers[3] -> boom

j is now out of range of the valid indices of numbers, so when you attempt to access numbers[j] the behavior of your program becomes undefined. In this case, it crashed; the best possible outcome.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
0

as the above comments pointed it out,

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

here 'int i' hides the previous local declaration of 'int i = 0;' (C4456), which is not desirable.

and the problem is that although i is bound to the range [0, n-1], j is not, which can cause access violation when j exceeds the range.

  • *"although i is bound to the range [0, n-1],"* -- not necessarily true, and not relevant. Since this `i` is not initialized, it could potentially start outside that range (unspecified initial value). Also, this `i` is never used as an index, so its values are not relevant. Your observation about `j`, though, is accurate. – JaMiT Aug 24 '22 at 04:58
  • Oh, you're right. I forgot that the second i was not initialized while I was writing my answer :) Thanks for pointing it out for me! – Jesús Jangwon Kim Aug 24 '22 at 07:43
0

You can use below code which will pass your all test cases.

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;
    }
};