heap-buffer-overflow on address - c++

Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array.
Example 1:
Input: [3,0,1]
Output: 2
My approach is read each element and then multiply that index by -1. Whichever array index remains positive is the one that's missing (I have to handle zero separately)
My code causes a heap overflow on line where I try to multiply the element by -1
class Solution {
public:
int missingNumber(vector<int>& nums) {
bool zeroFound = false;
for(auto i = nums.begin(); i < nums.end(); i++) {
if(*i == 0) {
zeroFound = true;
} else {
int value = *i;
printf("Inner %d %d\n", value, nums[value -1]);
//nums[value - 1] = value * (-1);
}
}
if(!zeroFound) {
return 0;
} else {
int count = 1;
for(auto i = nums.begin(); i < nums.end(); i++, count++) {
if(*i > 0) {
return count;
}
}
}
return -1;
}
};

Learn to use a debugger.
Your problem is that after the first run through the loop, the input is [3, 0, -3]. When you process the final element, you try and access element -4, which is never going to end well.
Even if you use the absolute value of the element, your first run will have overwritten the last element - so you can no longer tell whether the input was [3, 0, 1] or [3, 0, 2].

Related

strange error in main and incorrect reading of a vector [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 months ago.
Improve this question
hi I was writing a code where near the vectors it returns true if they are placed in ascending order otherwise false, when I try to start the code it gives me this error that I cannot understand
main.cpp:9:5: error: conflicting types for 'main'
int main(int, const char *[]) {
^
./solution.cpp:30:5: note: previous definition is here
int main()
^
1 error generated.
the other error happens in the vector inAscOrder_3 in which it should return false but I don't understand why it doesn't return it.
the code.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool isAscOrder(vector<int> arr)
{
int size_array = arr.size()-1;
int min = 0;
int max = 0;
for (int j = 0; j < size_array; j++)
{
if (min == 0)
{
min = arr[j];
max = arr[j];
}
if (arr[j] > min)
{
return true;
}
if(arr[j]<min)
{
return false;
}
}
return false;
}
int main()
{
vector<int> inAscOrder_1 = {1, 2, 4, 7, 19}; // returns true
vector<int> inAscOrder_2 = { 1, 2, 3, 4, 5 }; // returns true
vector<int> inAscOrder_3 = { 1, 6, 10, 18, 2, 4, 20 }; // returns false
vector<int> inAscOrder_4 = { 9, 8, 7, 6, 5, 4, 3, 2, 1 }; // returns false because the numbers are in DESCENDING order
//test 1
if (isAscOrder(inAscOrder_1) == true)
{
cout << "test #1 passed! " << endl;;
}
if (isAscOrder(inAscOrder_2) == true)
{
cout << "test #2 passed! "<<endl;
}
if (isAscOrder(inAscOrder_3) == false)
{
cout << "test #3 passed! "<<endl;
}
if (isAscOrder(inAscOrder_4) == false)
{
cout << "test #4 passed! ";
}
return 0;
}
In your average C++ program, the main function is the singular entry and exit point for the program. When your executable is called, the program starts at main, and once main returns, the program releases all of its allocated resources and is terminated.
Your first issue arises because you have multiple declarations of the main function; the first is located at main.cpp:9:5, and the second is located at solution.cpp:30:5
As for your second issue, your function does not do what you think it does; any correlation between your expected outputs and the real outputs are pure coincidence.
bool isAscOrder(vector<int> arr)
{
// This gets the size of your vector, then subtracts 1.
// size_array is now the index of the last element in the vector,
// and can be accessed with arr[size_array] without throwing an exception.
int size_array = arr.size()-1;
int min = 0;
int max = 0; //< you never actually read the value from this
// This condition is true until (j == size_array), and once it is the for loop breaks the loop.
// Keep in mind, size_array is currently set to the index of the last ELEMENT in your vector;
// That means you're always skipping the last element in the vector.
// You can avoid this by checking either ( j < arr.size() ) or ( j <= size_array )
// ▼
for (int j = 0; j < size_array; j++)
{
// This is always triggered on the first loop because min is always set to 0 the first time.
// if every number in the vector is 0 (except for the last one),
// then this will trigger every single time.
// ▼▼▼▼▼▼▼▼
if (min == 0)
{
// ▼ Sets min to the value at arr[j]
min = arr[j];
max = arr[j];
// ▲ Sets max to the value at arr[j],
// so max is now equal to min.
// For tests 1-3, that value is `1`;
// for test 4, that value is `9`
// Here we check if the value at arr[j] is greater than min, and if it is-
// -we immediately break from the for loop and return true.
if (arr[j] > min)
{
return true;
}
// Here we check if the value at arr[j] is less than min, and if it is-
// -we immediately break from the for loop and return false.
if(arr[j]<min)
{
return false;
}
//< we never reach this point a second time unless ( arr[0] == arr[1] )
}
//< This is only ever reached if every element of arr except for
// the last one is set to the same number.
return false;
}
As an example of what this function is doing, I debugged it for you:
As you can see, the function returned true on the second loop; this is because arr[1](2) is greater than min(1).
inAscOrder_1
Returns true when j == 1, because inAscOrder_1[1] == 2, and 2 > 1
inAscOrder_2
Returns true when j == 1, because inAscOrder_2[1] == 2, and 2 > 1
inAscOrder_3
Returns true when j == 1, because inAscOrder_3[1] == 6, and 6 > 1
inAscOrder_4
Returns false when j == 1, because inAscOrder_4[1] == 8, and 8 < 9
This is a working example of what your function should be doing:
bool isAscOrder(vector<int> arr)
{
if (arr.size() < 2) //< make sure arr[1] exists
return false;
// Start at 1 Don't skip the last element
// ▼ ▼▼▼▼▼▼▼▼▼▼▼▼▼
for (int i{ 1 }; i < arr.size(); ++i) {
// Check if arr[i] is less than or equal to arr[i - 1], this is
// why we started at 1 instead of 0; to prevent accessing arr[-1]
// ▼ ▼▼▼▼▼
if (arr[i] <= arr[i - 1])
return false;
// This approach works because if the sequence is in ascending order,
// each number in arr is never less than the previous one. (except for arr[0], which doesn't have a previous number)
}
return true;
}
You can allow a vector with repeated numbers to return true with this variant:
bool isAscOrder(vector<int> arr, bool allowRepeats = false)
{
if (arr.size() < 2) //< make sure arr[1] exists
return false;
for (int i{ 1 }; i < arr.size(); ++i) {
if (allowRepeats
? ( arr[i] < arr[i - 1] ) //< when allowing repeats, return false if the current element is less than the previous one.
: ( arr[i] <= arr[i - 1] ) //< when disallowing repeats, return false if the current element is less than or equal to the previous one.
)
{
return false;
}
}
return true;
}
When you're writing C++ code, having access to a debugger is incredibly important; if you're on Windows you can download and use Visual Studio Community for free.

Count how many iterations of deletion until array is ordered

I'm trying to write a program whose input is an array of integers, and its size. This code has to delete each element which is smaller than the element to the left. We want to find number of times that we can process the array this way, until we can no longer delete any more elements.
The contents of the array after we return are unimportant - only the return value is of interest.
For example: given the array [10, 9, 7, 8, 6, 5, 3, 4, 2, 1], the function should return 2, because:
[10,9,7,8,6,5,3,4,2,1] → [10,8,4] → [10]
For example: given the array [1,2,3,4], the function should return 0, because
No element is larger than the element to its right
I want each element to remove the right element if it is more than its right element. We get a smaller array. Then we repeat this operation again. Until we get to an array in which no element can delete another element. I want to calculate the number of steps performed.
int Mafia(int n, vector <int> input_array)
{
int ptr = n;
int last_ptr = n;
int night_Count = 0;
do
{
last_ptr = ptr;
ptr = 1;
for (int i = 1; i < last_ptr; i++)
{
if (input_array[i] >= input_array[i - 1])
{
input_array[ptr++] = input_array[i];
}
}
night_Count++;
} while (last_ptr > ptr);
return night_Count - 1;
}
My code works but I want it to be faster.
Do you have any idea to make this code faster, or another way that is faster than this?
Here is a O(NlogN) solution.
The idea is to iterate over the array and keep tracking candidateKillers which could kill unvisited numbers. Then we find the killer for the current number by using binary search and update the maximum iterations if needed.
Since we iterate over the array which has N numbers and apply log(N) binary search for each number, the overall time complexity is O(NlogN).
Alogrithm
If the current number is greater or equal than the number before it, it could be a killer for numbers after it.
For each killer, we keep tracking its index idx, the number of it num and the iterations needed to reach that killer iters.
The numbers in the candidateKillers by its nature are non-increasing (see next point). Therefore we can apply binary search to find the killer of the current number, which is the one that is a) the closest to the current number b) greater than the current number. This is implemented in searchKiller.
If the current number will be killed by a number in candidateKillers with killerPos, then all candidate killers after killerPos are outdated, because those outdated killers will be killed before the numbers after the current number reach them. If the current number is greater than all candidateKillers, then all the candidateKillers can be discarded.
When we find the killer of the current number, we increase the iters of the killer by one. Because from now on, one more iteration is needed to reach that killer where the current number need to be killed first.
class Solution {
public:
int countIterations(vector<int>& array) {
if (array.size() <= 1) {
return 0;
}
int ans = 0;
vector<Killer> candidateKillers = {Killer(0, array[0], 1)};
for (auto i = 1; i < array.size(); i++) {
int curNum = array[i];
int killerPos = searchKiller(candidateKillers, curNum);
if (killerPos == -1) {
// current one is the largest so far and all candidateKillers before are outdated
candidateKillers = {Killer(i, curNum, 1)};
continue;
}
// get rid of outdated killers
int popCount = candidateKillers.size() - 1 - killerPos;
for (auto j = 0; j < popCount; j++) {
candidateKillers.pop_back();
}
Killer killer = candidateKillers[killerPos];
ans = max(killer.iters, ans);
if (curNum < array[i-1]) {
// since the killer of the current one may not even be in the list e.g., if current is 4 in [6,5,4]
if (killer.idx == i - 1) {
candidateKillers[killerPos].iters += 1;
}
} else {
candidateKillers[killerPos].iters += 1;
candidateKillers.push_back(Killer(i, curNum, 1));
}
}
return ans;
}
private:
struct Killer {
Killer(int idx, int num, int iters)
: idx(idx), num(num), iters(iters) {};
int idx;
int num;
int iters;
};
int searchKiller(vector<Killer>& candidateKillers, int n) {
int lo = 0;
int hi = candidateKillers.size() - 1;
if (candidateKillers[0].num < n) {
return -1;
}
int ans = -1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (candidateKillers[mid].num > n) {
ans = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
return ans;
}
};
int main() {
vector<int> array1 = {10, 9, 7, 8, 6, 5, 3, 4, 2, 1};
vector<int> array2 = {1, 2, 3, 4};
vector<int> array3 = {4, 2, 1, 2, 3, 3};
cout << Solution().countIterations(array1) << endl; // 2
cout << Solution().countIterations(array2) << endl; // 0
cout << Solution().countIterations(array3) << endl; // 4
}
You can iterate in reverse, keeping two iterators or indices and moving elements in place. You don't need to allocate a new vector or even resize existing vector. Also a minor, but can replace recursion with loop or write the code the way compiler likely to do it.
This approach is still O(n^2) worst case but it would be faster in run time.

given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A

I tried to solve this exercise
I got 66 percent
I can not understand why
can you help?
The exercise is:
Write a function:
int solution(vector &A);
that, given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5.
Given A = [1, 2, 3], the function should return 4.
Given A = [−1, −3], the function should return 1.
The solution I wrote is:
#include <algorithm>
#include<cmath>
using namespace std;
int solution(vector<int> &A) {
if (A.size() == 0 || (A.size() == 1 && A.at(0) <= 0))
return 1;
if (A.size() == 1)
return A.at(0) + 1;
sort(A.begin(), A.end());
if (A.at(A.size() - 1) <= 0)
return 1;
auto ip = std::unique(A.begin(), A.end());
A.resize(distance(A.begin(), ip));
A.erase(remove_if(A.begin(), A.end(), [](const int i) { return i < 0; }),A.end());
if (A.at(0) != 1)
return 1;
if (A.size() == 1)
return (A.at(0) != 1 ? 1 : 2);
int i = 0;
for (; i < A.size(); ++i) {
if (A.at(i) != i + 1)
return A.at(i - 1) + 1;
}
return A.at(A.size()) + 1;
}
The following algorithm has a complexity O(n). No need to sort or to erase.
We know that the first missing value is less or equal to n+1, if n is the array size.
Then we simply have to use an array of size n+2, present[n+2], initialised to 0, and then to look at all values A[i]:
if (A[i] <= 1+n && A[i] > 0) present[A[i]] = 1;
Finally, in a second step we simply have to examine the array present[.], and search for the first index k such that present[k]==0.
#include <iostream>
#include <vector>
int find_missing (const std::vector<int> &A) {
int n = A.size();
std::vector<int> present (n+2, 0);
int vmax = n+1;
for (int i = 0; i < n; ++i) {
if (A[i] <= vmax && A[i] > 0) {
present[A[i]] = 1;
}
}
for (int k = 1; k <= vmax; ++k) {
if (present[k] == 0) return k;
}
return -1;
}
int main() {
std::vector<int> A = {1, 2, 0, 3, -3, 5, 6, 8};
int missing = find_missing (A);
std::cout << "First missing element = " << missing << std::endl;
return 0;
}
Well this is wrong
if(A.size()==1)
return A.at(0)+1;
If A is {2} that code will return 3 when the correct answer is 1
Also
A.erase(remove_if(A.begin(), A.end(),[](const int i) {return i < 0; }),A.end());
should be
A.erase(remove_if(A.begin(), A.end(),[](const int i) {return i <= 0; }),A.end());
Also
return A.at(A.size()) + 1;
is a guaranteed vector out of bounds error.
Even a small amount of testing and debugging would have caught these errors. It's a habit you should get into.
I think there are far too many special cases in the code, which only serve to complicate the code and increase the chance of bugs.
This answer is the implementation of the proposal given in the comment by PaulMcKenzie.
So, all credits go to PaulMcKenzie
It is not the fastest solution, but compact. The idea is basically.
Sort the data
Then compare the adjacent values, if the next value is equal to the previous value+1.
If not, then we found a gap. This can be implemented by using the function std::adjacent_find. Description can be found here.
We put all the side conditions into the lambda. If std::adjacent_find cannot find a value, then we take the next possible positive value.
I am not sure, what I could describe more. Please see the below example:
#include <iostream>
#include <vector>
#include <algorithm>
int solution(std::vector<int>& data) {
// Sort
std::sort(data.begin(), data.end());
// Check if there is a gap in the positive values
const auto gap = std::adjacent_find(data.begin(), data.end(), [](const int p, const int n) { return (n !=p) && (n != (p + 1) && p>0); });
// If there is no gap, the take the next positive value
return (gap == data.end()) ? (data.back() > 0 ? data.back() + 1 : 1) : *gap + 1;
}
int main() {
//Some test cases
std::vector<std::vector<int>> testCases{
{1,3,6,4,1,2},
{1,2,3},
{-1,-3}
};
for (auto& testCase : testCases)
std::cout << solution(testCase) << '\n';
return 0;
}
others have already pointed out what are the main errors, but I would like to invite you to try a different solution instead of trying to fix all the bugs and spend much time on debugging, because your solution seems a little overcomplicated.
Here I propose a way you can think about the problem:
What is the minimum number the function can return? Since it returns a positive integer, it is 1, in the case 1 is not in the array. Since that we can use any number <=0 to see if we found our result scanning the vector (see next);
In case one is not in the array, how do I find the wanted number? Your intuition is correct, if your vector is sorted it is easier: you can iterate over your data, and when you find an "hole" between two subsequent elements, then the value of the first element of the hole + 1 is you result
What do I do if the array contains 1 and has no holes? Well, you return the smallest element that is not in the array, so the last element + 1. You may notice that by checking if your "candidate" value (that is a number that shouldn't be returned, so <=0) has changed during the scanning;
Let's go to the code:
int solution(std::vector<int>& v){
int retVal=0;
std::sort(v.begin(), v.end());
for(int i=0; i<v.size()-1; i++){
if(v[i]>0 && v[i+1]>v[i]+1){
retVal=v[i]+1;
break;
}
}
if(retVal==0) {
if (v.back() > 0)
retVal = v.back() + 1;
else
retVal = 1;
}
return retVal;
}
As suggested you can use the standard library a little bit more, but I think this is reasonably simple and efficient.
Other note:
I think your assignment does not bother you with this, but I mention just for completeness. Most of the times you don't want a function to modify your parameters: you can pass the vector "by value" meaning that actually you pass a complete copy of your data, without touching the original one, or you can pass a const reference and create a copy inside the function.

Longest Consecutive Sequence in Array C++

I have to create a function that will find the longest consecutive sequence of integers in an array.
The array is this:
{1,2,3,4,4,4,5,7,9,10}
Note: repeated numbers in a sequence are skipped.
Here is my code:
int longestSequence(const int arr[], int size)
{
int currentSeq = 1;//set to 1 because all sequences are at least 1
int maxSeq;
for (int i = 1; i < size; i++)
{
if (arr[i] == arr[i-1]);//skip repeated numbers
else if (arr[i-1] == (arr[i] - 1))//check if index is 1 greater than last
{
currentSeq++;
}
else //if not reset and hold last sequence value as max
{
maxSeq = currentSeq;
currentSeq = 1;
}
}
if (currentSeq > maxSeq) //if the last index of the array was last in the sequence
{
maxSeq = currentSeq;
}
return maxSeq;
}
My code keeps returning 2 for this array but obviously it should be 5.
Any help would be appreciated.
You have 3 sequences in your array:
1, 2, 3, 4, 4, 4, 5 which has 5 consecutive numbers.
5, 7 which is not consecutive and will return 1.
7, 9 which will also return one.
9, 10 which has 2 consecutives and will return two.
In your loop you're doing this:
for (int i = 1; i < size; i++)
{
if (arr[i] == arr[i-1]);//skip repeated numbers
else if (arr[i-1] == (arr[i] - 1))//check if index is 1 greater than last
{
currentSeq++;
}
else //if not reset and hold last sequence value as max
{
maxSeq = currentSeq; // <-- You're resetting your maxSequence even if
// currentSeq is smaller.
currentSeq = 1;
}
}
Change your loop as following:
for (int i = 1; i < size; i++)
{
if (arr[i] == arr[i-1])
continue; //It is a good practice to skip the rest of the loop's
//checks if you already know you're not gonna need them.
//The continue keyword skips only the current iteration of
//the loop and improves intent readability.
else if (arr[i-1] == (arr[i] - 1))//check if index is 1 greater than last
{
currentSeq++;
}
else //if not reset and hold last sequence value as max
{
currentSeq = 1; //This line stays.
//You only want to reset it under these specific conditions.
}
if (currentSeq > maxSeq) // Now you'll get the last sequence as well.
maxSeq = currentSeq;
}
You can remove that check outside of the loop and go straight to the return. The last currentSeq will be properly registred if it is bigger than maxSeq.
Also, when I did this change I got a compile error because the new if (currentSeq > maxSeq) inside the loop tries to read maxSeq before it is ever set. So change the declaration of maxSeq to int maxSeq = 0.
With these changes I got the expected value of 5.
By running your program in a debugger with the sample array you provided, I determined that the variable currentSeq does indeed reach the value 5 and this value 5 is correctly written to maxSeq. However, later in the program, maxSeq gets overwritten by the value 1 and then 2.
Before overwriting maxSeq, you must determine whether it already contains a higher value than currentSeq. You already do this in one case, when you have reached the end of the array. But you don't do this in the other case.
For such a comparison to work, you must also initialize maxSeq, not just currentSeq. Otherwise, maxSeq may contain a very large number and always be larger than currentSeq.
#include <iostream>
void Log(int idx, int currentSeq, int maxSeq) {
printf("current[%d] = %d, max[%d] = %d\n", idx, currentSeq, idx, maxSeq);
}
int LongestSequence(int* arr, int size) {
int currentSeq = 1;
int maxSeq = 1; // max should be initialized as well
Log(0, currentSeq, maxSeq);
for (int i = 1; i < size; i++) {
if (arr[i] == arr[i - 1]) {
} else if (arr[i - 1] == (arr[i] - 1)) {
currentSeq++;
} else {
currentSeq = 1;
}
// maxSeq should be updated in time, otherwise it would be tossed away
maxSeq = std::max(maxSeq, currentSeq);
Log(i, currentSeq, maxSeq);
}
return maxSeq;
}
int main() {
int arr[] = {1, 2, 3, 4, 4, 4, 5, 7, 9, 10};
std::cout << LongestSequence(arr, sizeof(arr) / sizeof(arr[0])) << std::endl;
}
Output:
current[0] = 1, max[0] = 1
current[1] = 2, max[1] = 2
current[2] = 3, max[2] = 3
current[3] = 4, max[3] = 4
current[4] = 4, max[4] = 4
current[5] = 4, max[5] = 4
current[6] = 5, max[6] = 5
current[7] = 1, max[7] = 5
current[8] = 1, max[8] = 5
current[9] = 2, max[9] = 5
5

move zeros in an array to the end

"The question comes under a broad category of "Array Transformation". This category is the meat of tech interviews. Mostly because arrays are such a simple and easy to use data structure. Traversal or representation doesn't require any boilerplate code and most of your code will look like the Pseudocode itself.
The 2 requirements of the question are:
Move all the 0's to the end of array.
All the non-zero elements must retain their original order."
My thinking:
to find the zeros and exchange their positions with the last numbers
/* int swap;
int n=nums.size()-1;
for(int i=0;i<nums.size();i--){
if(nums[i]==0){
swap = nums[i];
nums[i] = nums[n];
nums[n] = swap;
n--;
}
}
My input
[0,1,0,3,12]
Output
[1,3,12,0,0]
Diff
Expected
[1,3,12,0,0]
And I did not know why the correct answer(the part) is :
(int n = 0, cur = 0; cur < nums.size(); cur++) {
if (nums[cur] != 0) {
swap(nums[n++], nums[cur]);
}
}
}
Can you use the standard library? std::stable_partition() makes it trivial. Something like
std::stable_partition(nums.begin(), nums.end(),
[](const auto &n){ return n != 0; });
For the question of how the solution in your post works:
At the start of the first iteration, n is 0, cur is 0, and nums is [0,1,0,3,12]. nums[cur] is 0, so nothing happens. At the start of the second iteration, cur is 1, and nums[cur] is 1, so the swap and increment of n happens.
Now n is 1, cur is 2, and nums is [1,0,0,3,12]. nums[cur] is 0, so nothing happens in the third iteration. In the fourth iteration, with cur now 3, a swap happens. So at the start of the the fifth iteration, n is 2, cur is 4, and nums is [1,3,0,0,12]. I'll leave it to you to work out what happens in that step.
Basically, when n is not equal to cur, it's the index of a 0 element that can be swapped with a non-0 element that cur is the index of. This swapping eventually moves all 0's to the end.
My take on the problem, minimal std library usage. Probably not the most efficient, but it does the trick.
#include "stdafx.h"
#include <iostream>
int main()
{
int src[] = { 0, 1, 0, 3, 0, 12 }; // Output: 1 3 12 0 0 0 check
// = { 0, 3, 0, 1, 0, 0, 12, 0, 5 }; // Output: 3 1 12 5 0 0 0 0 0 check
int n = sizeof(src) / sizeof(src[0]);
for (int x = 0; x < n; x++) {
for (int y = x + 1; y < n; y++) {
if (src[x] == 0 && src[y] != 0) {
int swap = src[x];
src[x] = src[y];
src[y] = swap;
}
}
}
for (int i = 0; i < n; i++) {
std::cout << src[i] << " ";
}
return 0;
}