AlmostIncreasingSequence(CodeSignal) - c++

I'm stuck in this challenge, and I thought of an algorithm which goes by:
bool almostIncreasingSequence(std::vector<int> Sequence)
{
int counter = 0;
Label:
std::vector<int>::iterator it = Sequence.begin();
for (it; it != Sequence.end(); it++)
{
if (*(it) >= *(it + 1))
{
counter++;
Sequence.erase(it);
goto Label;
}
}
return counter <= 1;
}
But I don't know why the output isn't right? What am I doing wrong in this code?
Here are the pictures of the challenge:

Make the return condition <= 2 and add an extra if statement to check if you would go out of bounds or not:
bool almostIncreasingSequence(std::vector<int> Sequence)
{
int counter{ 0 };
Label:
std::vector<int>::iterator it = Sequence.begin();
for (it; it != Sequence.end(); it++)
{
if ((it + 1 != Sequence.end())) //new if statement here
if (*(it) >= *(it + 1))
{
++counter;
Sequence.erase(it);
goto Label;
}
}
return counter <= 2;
}
hope it works!

Sorry I cant comment I need at least 50 rep, anyways... it has to do with the Label and goto statements, I have never seen such implementation, however removing the label and goto would work and make counter <= 1:
bool almostIncreasingSequence(std::vector<int> Sequence)
{
int counter{ 0 };
std::vector<int>::iterator it = Sequence.begin();
for (it; it != Sequence.end(); it++)
{
if ((it + 1 != Sequence.end()))
if (*(it) >= *(it + 1))
{
++counter;
}
}
return counter <= 1;
}
Here is an explanation: the goto statement is preventing the for statement from incrementing (++it), in other words using the goto would skip the increment part. This is what I think, again best of luck.

bool almostIncreasingSequence(vector<int> v) {
int n = v.size();
int cnt =0;
if(n == 1 )
return true;
for(int i=0; i<n-1; i++)
{
if(v[i]>=v[i+1])
{
if((v[i]-v[i+2] == 0))
cnt = 10;
cnt++;
}
}
if(cnt<=1)
return true;
else
return false;
}
was able to solve 17/19 test cases...let me know any further suggestions in this code.
Error for this test case [40, 50, 60, 10, 20, 30] .
problem statement link

Related

Leetcode 28 - Implement strStr(): question

I am experiencing a bug in my submissions for Leetcode 28 that has thus far eluded me. My code works for most test cases but I am getting hung up on scenarios such as haystack = "mississippi", needle = "issip".
I have tried debugging and found that the entire haystack string is iterated through and it is returning -1 or not found. The substring length it is finding at each occurrence of 'i' is 4, 1, 1.
int strStr(string haystack, string needle) {
if (needle.empty()) {
return 0;
}
if (haystack.empty() && !needle.empty()) {
return -1;
}
int i = 0, j = 0, ans = 0;
for (i; i < haystack.length(); i++) {
if (haystack[i] == needle[0]) {
j = 0;
ans = i;
for (j; j < needle.length(); j++) {
/*
if (haystack[i++] == needle[j]) {
continue;
}
else {
break;
}
*/
if (haystack[i++] != needle[j]) {
break;
}
}
if (j == needle.length()) {
return ans;
}
}
if (j == needle.length()) {
return ans;
}
}
return -1;
}
Input: "mississippi", "issip"
Output: -1 (ans = 10, j = 1)
The function has several drawbacks.
For starters it should be declared like
std::string::size_type strStr( const std::string &haystack, const std::string &needle );
and if the second string is not found in the first string the function should return std::string::npos as all similar member functions of the class std::string do.
The function parameters shell be of constant referenced types.
The condition in this if-statement
if (haystack.empty() && !needle.empty())
has a redundant operand. It could be rewritten like
if (haystack.empty())
This loop
for (i; i < haystack.length(); i++)
should stop its iterations when the size of the tail of the first string is less than the size of the second string.
in this if-statement
if (haystack[i++] != needle[j]) {
the variable i is incremented that results in incrementing the variable two times: one in this statement and the second time in the loop.
The second pair of these statements
if (j == needle.length()) {
return ans;
is redundant.
The function can be written the following way as it is shown in the demonstrative program.
#include <iostream>
#include <string>
std::string::size_type strStr( const std::string &haystack, const std::string &needle )
{
if ( needle.empty() )
{
return 0;
}
else if ( haystack.empty() )
{
return -std::string::npos;
}
else
{
std::string::size_type ans = std::string::npos;
auto n1 = haystack.length();
auto n2 = needle.length();
for ( std::string::size_type i = 0; ans == std::string::npos && i + n2 <= n1; i++ )
{
std::string::size_type j = 0;
while ( j < n2 && haystack[i+j] == needle[j] ) j++;
if ( j == n2 ) ans = i;
}
return ans;
}
}
int main()
{
std::string haystack( "mississippi" );
std::string needle( "issip" );
std::cout << strStr( haystack, needle ) << '\n';
return 0;
}
Its output is
4
The problem is that you modify i in
if (haystack[i++] != needle[j]) {
Thus preventing a second potential match from being explored. Try
if (haystack[i + j] != needle[j]) {
and fix any knock-on issues. I expect it to work as-is, though.

How to define the begin and the end value in C++?

I have an array like this:
600
250
600
600
600
I want to define the begin and the end indexes of this array where the value is greather than 500.
I made a variable which value is 2, because there are two section in my array where the values are greather than 500 (1-1 and 3-5).
So how could I output this:
1 1 3 5
The first 1 means the begin index is 1, the second 1 means the end index is also 1.
The 3 means the next section begin index where the value is greather than 500 is 3.
And the 5 means the end index of the second section is 5.
Using std:
std::vector<std::pair<std::size_t, std::size_t>>
compute_range_greater_than(const std::vector<int>& v, int threshold)
{
std::vector<std::pair<std::size_t, std::size_t>> res;
for (auto it = v.begin(); it != v.end(); /*Empty*/)
{
auto beg = std::find_if(it, v.end(), [=](int i) { return !(i < threshold); });
if (beg == v.end()) {
return res;
}
it = std::find_if(beg, v.end(), [=](int i) { return i < threshold; });
// using 1-index
res.push_back({1 + std::distance(v.begin(), beg), std::distance(v.begin(), it)});
}
return res;
}
Live Demo
Try this:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
v.push_back(10);
v.push_back(200);
v.push_back(170);
v.push_back(160);
v.push_back(20);
v.push_back(300);
v.push_back(12);
v.push_back(230);
std::vector<int> indexes;
int limit = 150;
bool started = false;
for (int i = 0; i < v.size(); i++)
{
int value = v[i];
if (value > limit && !started)
{
started = true;
indexes.push_back(i);
}
else if (value < limit && started)
{
started = false;
indexes.push_back(i - 1);
}
}
if (started)
indexes.push_back(v.size() - 1);
for (int i = 0; i < indexes.size(); i++)
{
if (i % 2 == 0)
std::cout << indexes[i] << "-";
else
std::cout << indexes[i] << "; ";
}
return 0;
}
Here limit is 150, but you can change it. Output is
1-3; 5-5; 7-7;
Good luck :)
You really should consider improving your question by better explaining what you want to do and by providing code that you already wrote (and if you didnt you should do it). However, I am in a good mood, so here you go:
#include <vector>
#include <iostream>
struct BeginAndEndIndex{
int begin;
int end;
BeginAndEndIndex(int begin) : begin(begin),end(begin) {}
};
typdef std::vector<BeginAndEndIndex> IndexV;
typdef std::vector<int> IV;
IndexV findBeginAndEndIndex(const IV& in,int threshold){
IndexV result;
bool isBiggerThanThreshold = false;
for (int i=0;i<in.size();i++){
if (!isBiggerThanThreshold) {
if (in[i]>threshold){
result.push_back(BeginAndEndIndex(i));
isBiggerThanThreshold = true;
}
} else {
if (in[i]<threshold){
result.back().end = i-1;
isBiggerThanThreshold = false;
}
}
}
if (isBiggerThanThreshold){result.back().end = in.size()-1;}
return result;
}
int main(void) {
IV foo {600,250,600,600,600};
IndexV bar = findBeginAndEndIndex(foo,500);
for (int i=0;i<bar.size();i++){
std::cout << bar[i].begin << " " << bar[i].end << std::endl;
}
return 0;
}
I am pretty sure that there is a more elegant way to implement it by using std::algorithms.
Just in straight C and not storing the indices anywhere, the following code produces the exact output that you are asking for:
#include <stdio.h>
int main(int argc, char **argv)
{
int values[] = {600, 250, 600, 600, 600};
int threshhold = 500;
int begIndex = -1;
int endIndex = -1;
int i;
for (i = 0; i < sizeof(values)/sizeof(values[0]); i++)
{
if (values[i] > threshhold)
{
if (begIndex < 0)
{
begIndex = i;
}
endIndex = i;
}
else if (begIndex >= 0)
{
printf("%d %d ", begIndex + 1, endIndex + 1);
begIndex = endIndex = -1;
}
}
if (begIndex >= 0)
printf("%d %d", begIndex + 1, endIndex + 1);
printf("\n");
return 0;
}
Keep in mind the arrays in C/C++ start at zero, not one. Changing the above code to store the begIndex and endIndex pairs should be a trivial operation.

Count of consecutive numbers in a vector

Suppose I have the following sorted vectors as input:
[22]
[22, 23]
[22, 46]
[22, 46, 47]
[22,23,33,44,45,46,55,56]
I want the following output which shows the count of consecutive numbers in each vector:
1 //edgecase: if there's 1 number it's consecutive)
2 //22, 23 are 2 consecutive numbers
0 //22, 46 not consecutive
2 //46, 47 are 2 consecutive numbers
7 //22,23 (2) 44,45,46 (3) 55,56(2) 7 consecutive numbers
My vector will not have duplicates.
What I have so far is:
vector<int> numbers;
int consecCount=0;
if (numbers.size()==1)
consecCount++;
else{
for (size_t k=1; k<numbers.size(); k++) {
if (numbers[k]==numbers[k-1]+1) {
consecCount +=2;
}
}
Of course this method doesn't work for the last array. The solution seems really wrong.
My actual vectors are really large, so prefer any ideas that does not involve using a another vector
Something like this?
size_t conseccount(const vector<int> &v)
{
size_t s = v.size();
size_t ret = 0;
bool seqstart = true;
if(s < 2) return 0;
for(size_t i = 1; i < s; i++)
{
if(v[i - 1] + 1 == v[i])
{
if(seqstart) ret++;
seqstart = false;
ret++;
}
else seqstart = true;
}
return ret;
}
Expected output
vector question why my query
1 1 22 Is it 1 or 0. // I don't understand why
2 2 22,23
3 0
4 2 46,47
5 7 22,23 44,45,46 55,56
That is count the number of entries which are part of sequences such that a[i] = a[i+1]
The key to this is to ensure you count singly, but add one at the end of a sequence.
You need to check whether you are in a sequence bool bInSequence, which is false initially. When you transition into a sequence, you set it to true.
Then when you leave a sequence, or the loop, you add one.
vector<int> numbers;
int consecCount=0;
if (numbers.size()==1)
consecCount++;
else{
bool inSequence = false;
for (size_t k=1; k<numbers.size(); k++) {
if (numbers[k]==numbers[k-1]+1) {
consecCount +=1;
inSequence = true;
} else if ( inSequence ) {
inSequence = false;
consecCount ++;
}
}
if( inSequence == true ) {
// inSequence = false; //not needed, but logically correct
consecCount ++;
}
}
With std::adjacent_find, you may do something like:
std::size_t count_consecutive_sequence(const std::vector<int> &v)
{
if (v.size() <= 1) {
return v.size();
}
std::size_t res = 0;
for (auto it = v.begin(); it != v.end(); ) {
auto e = std::adjacent_find(it, v.end(),
[](int lhs, int rhs) { return lhs + 1 != rhs; });
if (it == e || it + 1 == v.end()) {
++it;
} else {
if (e != v.end()) {
++e;
}
res += distance(it, e);
it = e;
}
}
return res;
}
Demo

Find if in an array there are at least once all the numbers from 1 to K

Yesterday I did a test on C++ for an interview and I had to find bugs in the following code.
The algorithm takes in input a vector of integer sorted in a non-decreasing order and an integer K. The algorithm returns true if the vector contains only and all the numbers between 1 and k at least once, and false otherwise:
([1,1,2,3,3,4],4) --> true
([1,1,3],3) --> false
This was the implementation:
bool algorithm(vector<int> &A, int k)
{
n = A.size();
for(int i = 0; i < n-1; i++)
{
if(A[i]+1 < A[i+1])
return false;
}
if(A[0] != 1 && A[n-1] != K)
{
return false;
}
else
{
return true;
}
}
I wasn't able to find bug/bugs. Could someone tell me where is/are the bug/s in this code?
The final check should be an OR as either condition is sufficient reason to return false. For example, ([0,1,2],2) would pass as the code is now.
Also, this may be a typo on your part, but the k param is referenced as K (wrong case).
You just need to change at the if condition
Change 1st if condition to
if ((A[i] != A[i+1]) && (A[i] + 1 != A[i+1]) {
return false;
}
Change 2nd if condition to
if (A[0] != 1 || A[n-1] != K) {
return false;
}
Maybe a bit overdone, but guaranteed to be correct:
bool algorithmc(vector<int>& A, int k)
{
int n = A.size();
//null checking
if (n < k)
return false;
// easy checking
if(A[0] != 1 || A[n-1] != k)
return false;
vector<int> flags(k + 1, 0);
for (int i = 0; i < n - 1; i++) {
// all data less than and equal to k
if (A[i] <= k)
flags[A[i]] = 1;
else
return false;
// check the input is valid
if (A[i + 1] < A[i])
return false;
}
//check the last one
if (A[n - 1] <= k)
flags[A[n - 1]] = 1;
else
return false;
// this is to make sure all data in range 1..k appear.
for (int i = 1; i <= k; i++)
if (!flags[i])
return false;
return true;
}
int n = A.size(); // int is missing
Other than the ones pointed out above, the overall logic is not correct.
I think the bug is if given empty vector (no null check), and/or a vector starting with 0 will pass the test when it is supposed to fail. here is my solution
bool algorithm(vector<int> &A, int k)
{
int n = A.size();
//if vector is size zero return false;
if(n <=0)
return false;
bool vector_dont_have_one = A[0] != 1;
bool vector_dont_have_k = A[n-1] != k;
if(vector_dont_have_one || vector_dont_have_k)
{
return false;
}
for(int i = 0; i < n-1; i++)
{
bool is_not_sorted = A[i]+1 < A[i+1];
if(is_not_sorted){
return false;
}
}
return true;
}

C++ counting how many times data in array changes changed directions?

My program is suppose to count how many times the data in my array changed from increase to decrease or vice versa. For example: {1,2,3,4,3,4}
changes twice as the first four elements are increasing then decrease o 3 (causing one change) and then increase back to four causing a second change.
The idea in my code was that every time greater or decrease changed to false it would count when it happened but I cannot get it to work.
Any help is greatly appreciated as I am really struggling with this!
unsigned count = 0;
bool greater = true;
bool decrease = true;
for (unsigned i = 0; i < elements; i++){
if (a[i + 1] > a[i]){
greater = true;
}
else
greater = false;
count++;
}
for (unsigned i = 0; i < elements; i++){
if (a[i + 1] < a[i]){
decrease = true;
}
else
decrease = false;
count++;
}
return count;
Your logic is wrong
you may do something like
enum class EDirection { none, decreasing, increasing};
std::size_t count_direction_changes(const std::vector<int>& v)
{
std::size_t res = 0;
EDirection direction = EDirection::none;
for (std::size_t i = 1; i != v.size(); ++i) {
const int diff = v[i] - v[i - 1];
switch (direction)
{
case EDirection::none: {
if (diff == 0) {
break;
}
direction = (diff > 0) ? EDirection::increasing : EDirection::decreasing;
break;
}
case EDirection::increasing: {
if (diff < 0) {
++res;
direction = EDirection::decreasing;
}
break;
}
case EDirection::decreasing: {
if (diff > 0) {
++res;
direction = EDirection::increasing;
}
break;
}
}
}
return res;
}
Demo
You must change your loops. First of all you should stop the loop at size-1. Because you are comparing with next element and you can go out of bounds if your for is running until elements instead of elements-1.
Furthermore, you have a logic issue. If you are using a boolean variable as flag, you should check if it's true or not before increasing your counter. And in case you increments your counter you must reset that flag. Something similar to down loop should work. Maybe there is some little mistake because I don't have anythin to test it now. But it should be something similar to this.
for (unsigned i = 0; i < elements-1; i++){
if (a[i + 1] > a[i]){
greater = true;
}
else{
greater = false;
}
if(greater){
count++;
greater = false;
}
}
This is a lot like Jarod42's, but seeing as I've already coded it will throw it out there. BTW, I use the slightly awkward v[n] < v[n - 1] so it's only necessary to implement operator< to apply the algo to a user-defined type (i.e. not operator> as well).
#include <iostream>
#include <vector>
template <typename T>
size_t changes(const std::vector<T>& v)
{
if (v.size() <= 2) return 0;
size_t count = 0;
enum { Increasing, Decreasing, Flat } last;
last = v[0] < v[1] ? Increasing : v[1] < v[0] ? Decreasing : Flat;
for (size_t i = 2; i < v.size(); ++i)
if (v[i - 1] < v[i])
{
if (last == Decreasing) ++count;
last = Increasing;
}
else if (v[i] < v[i - 1])
{
if (last == Increasing) ++count;
last = Decreasing;
}
return count;
}
int main()
{
std::cout << changes<int>({ 1, 3, 5, 4, 6 }) << '\n';
std::cout << changes<int>({ 3, 3, 5, 4, 6 }) << '\n';
std::cout << changes<int>({ 4, 3, 5, 4, 2, 2, 1 }) << '\n';
}
See it run here.
Here is another approach, similar to Tony's and Jarod's:
#include <vector>
#include <cassert>
#include <iostream>
size_t countTrendChanges(const std::vector<int>& a) {
if (a.size() < 3)
return 0;
int trend = 0;
size_t count = 0;
for (size_t i = 1; i != a.size(); ++i) {
int new_trend = (a[i-1] < a[i]) - (a[i] < a[i-1]);
if (new_trend == 0)
continue;
if (trend != 0 && new_trend != trend)
count++;
trend = new_trend;
}
return count;
}
int main() {
assert(countTrendChanges({}) == 0);
assert(countTrendChanges({1}) == 0);
assert(countTrendChanges({3,2,1}) == 0);
assert(countTrendChanges({1,2,3}) == 0);
assert(countTrendChanges({1,2,2,3}) == 0);
assert(countTrendChanges({3,2,1,2,3}) == 1);
assert(countTrendChanges({1,2,3,2}) == 1);
assert(countTrendChanges({2,1,1,2}) == 1);
assert(countTrendChanges({1,2,2,1}) == 1);
assert(countTrendChanges({1,2,3,4,3,4}) == 2);
}