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
Related
I was solving a Majority_element problem, where I would be provided an int 'n' followed by an array whose size is n, as input. If any element's frequency in the array is more than n/2, then return 1, otherwise, return 0. Now, my program works correctly for small values of integer elements, but it's giving a false output for bigger int values.
Here's the source code
#include <algorithm>
#include <iostream>
#include <vector>
using std::vector;
int get_majority_element(vector<int> &a) {
int count{};
std::sort(a.begin(),a.end());
for( size_t i{}; i<a.size() ; ++i ){ //counter
for( size_t j = i+1 ; j<a.size() ; ++j ){
if( a.at(i) == a.at(j) ){
count += 1; // may have to inclue a count nullifier if two elements are repeated
}
}
}
if( count > ( a.size()/2 ) ){
return 1;
}
else {
return 0;
}
}
int main() {
int n;
std::cin >> n;
vector<int> a(n);
for (size_t i = 0; i < a.size(); ++i) {
std::cin >> a.at(i);
}
std::cout << get_majority_element(a) << '\n';
return 0;
}
Here are some outputs
6
1 1 1 2 3 4
0
6
1 1 1 1 2 3
1
10
512766168 717383758 5 126144732 5 573799007 5 5 5 405079772
1 ( should be 0)
Now could somebody please explain to me what's going wrong? I even tried setting vector data type to long long to prevent potential memory leaks.
As you do,
you don't need std::sort.
you need to reset count.
check should be done in outer loop
bool get_majority_element(const vector<int> &a) {
for (size_t i{}; i < a.size() ; ++i) {
int count{};
for (size_t j = i+1 ; j<a.size() ; ++j) {
if (a.at(i) == a.at(j)){
count += 1;
}
}
if (count > ( a.size()/2 )) {
return true;
}
}
return false;
}
or
bool get_majority_element(const vector<int> &a) {
for (size_t i{}; i < a.size() ; ++i) {
if (std::count(a.begin() + i, a.end(), a[i]) > a.size() / 2) {
return true;
}
}
return false;
}
Complexity: O(n²).
Once sorted, equal elements are adjacent, so you don't need to check each element:
bool get_majority_element(vector<int> &a) {
std::sort(a.begin(), a.end());
for (auto it = a.begin(); it != a.end(); /*empty*/) {
auto next = std::find_if(it, a.end(), [&](int n){ return n != *it; });
if (std::distance(it, next) > a.size() / 2) {
return true;
}
it = next;
}
return false;
}
Complexity: O(n lon n).
For info, there exist also an algorithm to do it linearly which consist to find possible candidate, and then check it.
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
I have an array which spans as follows. So the example to understand is consider a block with 6 faces. The array contains the index in this array from which the faces for a particular colour will start.
array[0] 0
array[1] 2
array[2] 4
array[3] 5
so this means that colour 0 is for faces 0 and 1, colour 1 is for faces 2 and 3,
and colour 2 is only for face 4
But the array will not always look like this. if there is a block with just a single colour the array would look like
array[0] 0
array[1] 1
which means face 0 is coloured with 0 color, and faces 1,2,3,4,5 are coloured with color 1
I will get an input as the face number and need to find the corresponding colour
I tried it with a for loop
for (int index = 0; index < array.size(); ++index)
{
if (array[index] == input)
{
return index;
}
if (array[index] < input)
{
return index - 1;
}
}
but the answer is not always correct . Can this be done with while . Please help
As I understand, you want to find the largest index of the array which is less or equal to the given input.
Then you can use the following with binary search.
std::size_t getIndexFor(const std::vector<int>& v, int input)
{
auto it = std::lower_bound(v.begin(), v.end(), input);
if (it != v.begin() && (it == v.end() || *it != input)) {
--it;
}
return std::distance(v.begin(), it);
}
Demo
A simpler (and linear) way:
std::size_t getIndexFor(const std::vector<int>& v, int input)
{
auto it = std::find_if(v.begin(), v.end(), [&](int e){ return e > input;});
if (it == v.begin()) {
throw std::runtime_error("input not handled");
}
--it;
return std::distance(v.begin(), it);
}
Demo
You would just do the same thing, looping through the array to search for the term you want. Of course if it's a sorted array this would be much faster, so something similar to prehaps:
for(int i = 0; i < arraySize; i++){
if(array[i] == itemToFind){
break;
}
}
You are very close to the right solution, just change array[index] < input into array[index] > input:
#include <iostream>
#include <vector>
std::vector<int> array = {0, 2, 4, 5};
int subs(int input)
{
for (int index = 0; index < array.size(); ++index)
{
if (array[index] == input)
{
return index;
}
if (array[index] > input)
{
return index - 1;
}
}
return -1;
}
int main(int argc, const char *argv[])
{
for (int i = 0; i <= 5; i++) {
std::cout<<"input: "<<i<<" "<<"color: "<<subs(i)<<std::endl;
}
return 0;
}
This gives:
input: 0 color: 0
input: 1 color: 0
input: 2 color: 1
input: 3 color: 1
input: 4 color: 2
input: 5 color: 3
I used the for loop also but using break after one if condition that checks if the input equals any element in the array.
#include <iostream>
using namespace std;
int main(){
string arr = " ";
int x;
cout << "Enter your input";
cin >> x;
for (int i =0; i< arr.length(); i++ ){
if (arr[i] == x){
break;
}
}
return 0;
}
Another, maybe simpler solution:
int findIndex( const std::vector<int>& vec, int input )
{
int count = vec.size()-1;
for ( auto it = vec.rbegin(); it != vec.rend(); it++)
{
if ( *it<=input )
{
return count;
}
count--;
}
return -1; // if nothing found
}
int main()
{
std::vector<int> vec { 0,2,4,5 };
for ( int input=0; input <=5; input++)
{
std::cout << findIndex( vec, input ) << " " << input << std::endl;
}
}
Output:
0 0
0 1
1 2
1 3
2 4
3 5
I want to write a program that stores the sum of 2 numbers in an array and retrieves it in the order in which it was generated. I know that map stores the key in sorted order. Unordered_map stores the keys in an order which is definitely not based on sequence of generation.
Is there some way i can use STL to get what i want in c++ ?
Below is my code for the program. I need to find an array of 4 numbers where A+B = C+D such that all are unique and are lexicographically sorted.
Array = 1 3 3 3 3 2 2
I should get 0 1 6 7 as output but instead i am getting 1 5 2 6.
vector<int> Solution::equal(vector<int> &A) {
vector<int> result;
unordered_map<int,vector<vector<int>>> hash;
int n = A.size();
for(int i = 0; i < n ; i++) {
for(int j = i+1; j < n; j++) {
int sum = A[i] + A[j];
vector<int> temp{i,j};
if (hash.find(sum) != hash.end()) {
hash[sum].push_back(temp);
}
else
hash.insert(make_pair(sum,vector<vector<int>>{temp}));
}
}
for(unordered_map<int,vector<vector<int>>>::iterator it=hash.begin(); it != hash.end(); it++) {
int size = it->second.size();
bool found = 0;
if( size > 1) {
for(int i = 1; i < size; i++) {
cout<<it->first<<" ";
if (it->second[0][0] == it->second[i][0] || it->second[0][1] == it->second[i][0] || it->second[0][1] == it->second[i][1]) continue;
result.push_back(it->second[0][0]);
result.push_back(it->second[0][1]);
result.push_back(it->second[i][0]);
result.push_back(it->second[i][1]);
found = 1;
break;
}
if (found) break;
}
}
return result;
}
I used the code in this topic
https://stackoverflow.com/a/5097100/3617657
and I edit it little bit to work on std::vector<std::vector<int>> instead std::vector<int>
K in my case has different values (from 1- to 4), instead only one single value
Example: my data
1 2 3 4
1 2 4
1 3
if k=3, Then for each line in my data, n choose k=
123
124
134
234
124
13
but I want my result in map, where the value represents the frequency of subset as:
(123, 1)
(124, 2)
(134, 1)
(234, 1)
(13, 1)
This is my code:
std::vector<std::vector<int>> data;
std::map <int, set<int>> CandidateSet;
typedef std::pair<set<int>, int> combo;
std::map <int, combo> CandidateSup;
void ScanData()
{
ifstream in;
in.open("mydata.txt");
/* mydata.txt
1 2 3 4 5
1 3 4 5
1 2 3 5
1 3
*/
std::string line;
int i = 0;
while (std::getline(in, line))
{
std::stringstream Sline1(line);
std::stringstream ss(line);
std::vector<int> inner;
int info;
while (ss >> info)
inner.push_back(info);
data.push_back(inner);
}
}
int main()
{
ScanData();
std::size_t k = 0;
int j = 0;
int c = 0;
int supp = 1;
int Lsize = 1;
while (Lsize <= 4)
{
for (unsigned i = 0; i < data.size(); ++i)
{
std::vector<int>::iterator items = data[i].begin();
if (Lsize > data[i].size())
k = data[i].size();
else
k = Lsize;
do
{
for (std::vector<int>::iterator items = data[i].begin(); j < k; ++items)
{
CandidateSet[c].insert(*items);
++j;
}
++c;
std::cout << "\n";
j = 0;
}
while (next_combination(data[i].begin(), data[i].begin() + k, data[i].end()));
/******************************************************************************************************************************
//here my problem
// check if the (next_combination) is already exist in CandidateSet, if yes add one to existing support
auto it = CandidateSet.begin();
set <int> A = it->second;
set <int> B;
B = CandidateSet[*items]; // I don't know how to set be as the next_combination
while (it != CandidateSet.end())
{ // if it found
if (!(A < B) && !(B < A))
{
CandidateSup[*items] = std::make_pair(A, ++supp);
break;
}
else
{ // if not found yet
++it;
A = it->second;
}
}// end while
// if it is not exist, add this new set with support =1
++c;
CandidateSup[c] = std::make_pair(B, supp);
/******************************************************************************************************************************/
}
++Lsize;
}
data.clear();
system("PAUSE");
return 0;
}
This "combination.h"
template <typename Iterator>
inline bool next_combination(const Iterator first, Iterator k, const Iterator last)
{
/* Credits: Thomas Draper */
if ((first == last) || (first == k) || (last == k))
return false;
Iterator itr1 = first;
Iterator itr2 = last;
++itr1;
if (last == itr1)
return false;
itr1 = last;
--itr1;
itr1 = k;
--itr2;
while (first != itr1)
{
if (*--itr1 < *itr2)
{
Iterator j = k;
while (!(*itr1 < *j)) ++j;
std::iter_swap(itr1, j);
++itr1;
++j;
itr2 = k;
std::rotate(itr1, j, last);
while (last != j)
{
++j;
++itr2;
}
std::rotate(k, itr2, last);
return true;
}
}
std::rotate(first, k, last);
return false;
}
The following may help: (https://ideone.com/5EPuGd)
std::map<std::set<int>, int> counts;
for (std::size_t Lsize = 1; Lsize <= 4; ++Lsize)
{
for (unsigned i = 0; i < data.size(); ++i)
{
std::size_t k = std::min(Lsize, data[i].size());
do
{
std::set<int> n_k(data[i].begin(), data[i].begin() + k);
++counts[n_k];
}
while (next_combination(data[i].begin(), data[i].begin() + k, data[i].end()));
}
}