Implement next combination - C_n_k on C++ using vector - c++

I am getting stuck - can't implement perfect algorithm for next Combination for lexicographical order. Could you please tell me where I get wrong? For instance, e.g. vector a = {1,2,0,3,0,1,2,4}; nextPermutation(a); has an overflow-heap when accessing to an element of the array std::next. How would this code be improved?
void nextPermutation(vector<int>& perm) {
auto temp1 = perm[0], temp2 = perm[0];
int idx1 = -1, idx2 = -1;
if (perm.size() == 1)
return;
if (perm.size() == 2)
{
reverse(perm.begin(), perm.end());
return;
}
for (auto &v : perm)
{
if (&v - &perm[0] == perm.size())
break;
if (v < *(&v + 1))
{
temp1 = v;
idx1 = &v - &perm[0];
//cout << idx1 << endl;
}
}
if (idx1 == -1)
{
reverse(perm.begin(), perm.end());
return;
}
for (auto v = perm.begin(); v < perm.end(); v++)
{
if (*v > *next(perm.begin(), idx1))
{
temp2 = *v;
idx2 = std::distance(perm.begin(), v);
//cout << idx2 << endl;
}
}
int temp = perm[idx1];
perm[idx1] = perm[idx2];
perm[idx2] = temp;
reverse(perm.begin() + idx1 + 1, perm.end());
}

Related

string subscript out of range error when assigning variable to function

In order to become more familiar with cpp I began making a program that takes the derivative of simple polynomials using the power rule. So far, it is working fine for polynomials such as 5x^2+4x. However, if the polynomial contains a constant (like 5x + 3) I get a string subscript out of range error. I used the debugger and found the error triggers on line 33 (std::string term = differentiateTerm(*iter);). I'm not exactly sure what I'm doing wrong here and I would appreciate any help.
Full code:
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string> terms;
std::vector<std::string>::const_iterator iter;
std::string takeDerivative(std::string expression);
void separateTerms(std::string expression);
std::string differentiateTerm(std::string inputTerm);
int main()
{
std::string userExpression;
std::cout << "Enter a polynomial.\n";
std::cin >> userExpression;
std::string outputExpression = takeDerivative(userExpression);
std::cout << "The derivative of your expression is: " + outputExpression;
return 0;
}
std::string takeDerivative(std::string expression)
{
std::string derivative;
separateTerms(expression);
for (iter = terms.begin(); iter != terms.end(); iter++)
{
std::string term = differentiateTerm(*iter);
if (iter - terms.begin() == 0)
{
derivative = term;
}
else
{
derivative += "+" + term;
}
}
return derivative;
}
void separateTerms(std::string expression)
{
int previousSign = 0;
bool firstTerm = true;
for (int i = 0; i < expression.size() + 1; i++)
{
if (expression[i] == '+' || expression[i] == '-')
{
if (firstTerm)
{
terms.push_back(expression.substr(0, i));
firstTerm = false;
previousSign = i;
}
else
{
terms.push_back(expression.substr(previousSign + 1, i - previousSign - 1));
previousSign = i;
}
}
else if (i == expression.size())
{
if (firstTerm)
{
terms.push_back(expression.substr(previousSign, i));
}
else
{
terms.push_back(expression.substr(previousSign + 1, i - previousSign));
}
}
}
}
std::string differentiateTerm(std::string inputTerm)
{
std::string outputTerm;
int coefficient = 1;
int exponent = 1;
int varPos = inputTerm.find('x');
if (inputTerm[varPos] == std::string::npos)
{
outputTerm = "0";
return outputTerm;
}
else {
if (inputTerm[varPos - 1] != std::string::npos)
{
coefficient = std::stoi(inputTerm.substr(0, varPos));
}
if (inputTerm[varPos + 1] == '^')
{
if (inputTerm[varPos + 2] != std::string::npos)
{
exponent = std::stoi(std::string(1, inputTerm[varPos + 2]));
}
}
}
coefficient = coefficient * exponent;
exponent--;
if (exponent <= 0)
{
outputTerm = std::to_string(coefficient);
}
else if (exponent == 1)
{
outputTerm = std::to_string(coefficient) + "x";
}
else
{
outputTerm = std::to_string(coefficient) + "x^" + std::to_string(exponent);
}
return outputTerm;
}
You're not checking the return value from find correctly in differentiateTerm. This causes inputTerm[varPos] to access out of bounds.
The correct check is
if (varPos == std::string::npos)
In the subsequent if statements, since you have a valid subscript in varPos, you should check that against the size of the string. So you'd have if (varPos > 0), if (varPos < inputTerm.size() - 1), etc.

Product of all the nodes on the path of a tree

I was learning MO's Algorithm. In that I found a question. In which we have to make a program to take input n for n nodes of a tree then n-1 pairs of u and v denoting the connection between node u and node v. After that giving the n node values.
Then we will ask q queries. For each query we take input of k and l which denote the two nodes of that tree. Now we have to find the product of all the nodes in the path of k and l (including k and l).
I want to use MO's algorithm. https://codeforces.com/blog/entry/43230
But I am unable to make the code. Can anybody help me out in this.
The basic code for that would be:
int n, q;
int nxt[ N ], to[ N ], hd[ N ];
struct Que{
int u, v, id;
} que[ N ];
void init() {
// read how many nodes and how many queries
cin >> n >> q;
// read the edge of tree
for ( int i = 1 ; i < n ; ++ i ) {
int u, v; cin >> u >> v;
// save the tree using adjacency list
nxt[ i << 1 | 0 ] = hd[ u ];
to[ i << 1 | 0 ] = v;
hd[ u ] = i << 1 | 0;
nxt[ i << 1 | 1 ] = hd[ v ];
to[ i << 1 | 1 ] = u;
hd[ v ] = i << 1 | 1;
}
for ( int i = 0 ; i < q ; ++ i ) {
// read queries
cin >> que[ i ].u >> que[ i ].v;
que[ i ].id = i;
}
}
int dfn[ N ], dfn_, block_id[ N ], block_;
int stk[ N ], stk_;
void dfs( int u, int f ) {
dfn[ u ] = dfn_++;
int saved_rbp = stk_;
for ( int v_ = hd[ u ] ; v_ ; v_ = nxt[ v_ ] ) {
if ( to[ v_ ] == f ) continue;
dfs( to[ v_ ], u );
if ( stk_ - saved_rbp < SQRT_N ) continue;
for ( ++ block_ ; stk_ != saved_rbp ; )
block_id[ stk[ -- stk_ ] ] = block_;
}
stk[ stk_ ++ ] = u;
}
bool inPath[ N ];
void SymmetricDifference( int u ) {
if ( inPath[ u ] ) {
// remove this edge
} else {
// add this edge
}
inPath[ u ] ^= 1;
}
void traverse( int& origin_u, int u ) {
for ( int g = lca( origin_u, u ) ; origin_u != g ; origin_u = parent_of[ origin_u ] )
SymmetricDifference( origin_u );
for ( int v = u ; v != origin_u ; v = parent_of[ v ] )
SymmetricDifference( v );
origin_u = u;
}
void solve() {
// construct blocks using dfs
dfs( 1, 1 );
while ( stk_ ) block_id[ stk[ -- stk_ ] ] = block_;
// re-order our queries
sort( que, que + q, [] ( const Que& x, const Que& y ) {
return tie( block_id[ x.u ], dfn[ x.v ] ) < tie( block_id[ y.u ], dfn[ y.v ] );
} );
// apply mo's algorithm on tree
int U = 1, V = 1;
for ( int i = 0 ; i < q ; ++ i ) {
pass( U, que[ i ].u );
pass( V, que[ i ].v );
// we could our answer of que[ i ].id
}
}
This problem is a slight modification of the blog that you have shared.
Problem Tags:- MO's Algorithm, Trees, LCA, Binary Lifting, Sieve, Precomputation, Prime Factors
Precomputations:- Just we need to do some precomputations with seiveOfErothenesis to store the highest prime factor of each element possible in input constraints. Then using this we will store all the prime factors and their powers for each element in input array in another matrix.
Observation:- with the constraints you can see the there can be very few such primes possible for each element. For an element (10^6) there can be a maximum of 7 prime factors possible.
Modify MO Algo Given in blog:- Now in our compute method we just need to maintain a map that will store the current count of the prime factor. While adding or subtracting each element in solving the queries we will iterate on the prime factors of that element and divide our result(storing total no. of factors) with the old count of that prime and then update the count of that prime and the multiple our result with the new count.(This will be O(7) max for each addition/subtraction).
Complexity:- O(T * ((N + Q) * sqrt(N) * F)) where F is 7 in our case. F is the complexity of your check method().
T - no of test cases in input file.
N - the size of your input array.
Q - No. of queries.
Below is an implementation of the above approach in JAVA. computePrimePowers() and check() are the methods you would be interested in.
import java.util.*;
import java.io.*;
public class Main {
static int BLOCK_SIZE;
static int ar[];
static ArrayList<Integer> graph[];
static StringBuffer sb = new StringBuffer();
static boolean notPrime[] = new boolean[1000001];
static int hpf[] = new int[1000001];
static void seive(){
notPrime[0] = true;
notPrime[1] = true;
for(int i = 2; i < 1000001; i++){
if(!notPrime[i]){
hpf[i] = i;
for(int j = 2 * i; j < 1000001; j += i){
notPrime[j] = true;
hpf[j] = i;
}
}
}
}
static long modI[] = new long[1000001];
static void computeModI() {
for(int i = 1; i < 1000001; i++) {
modI[i] = pow(i, 1000000005);
}
}
static long pow(long x, long y) {
if (y == 0)
return 1;
long p = pow(x, y / 2);
p = (p >= 1000000007) ? p % 1000000007 : p;
p = p * p;
p = (p >= 1000000007) ? p % 1000000007 : p;
if ((y & 1) == 0)
return p;
else {
long tt = x * p;
return (tt >= 1000000007) ? tt % 1000000007 : tt;
}
}
public static void main(String[] args) throws Exception {
Reader s = new Reader();
int test = s.nextInt();
seive();
computeModI();
for(int ii = 0; ii < test; ii++){
int n = s.nextInt();
lcaTable = new int[19][n + 1];
graph = new ArrayList[n + 1];
arrPrimes = new int[n + 1][7][2];
primeCnt = new int[1000001];
visited = new int[n + 1];
ar = new int[n + 1];
for(int i = 0; i < graph.length; i++) graph[i] = new ArrayList<>();
for(int i = 1; i < n; i++){
int u = s.nextInt(), v = s.nextInt();
graph[u].add(v);
graph[v].add(u);
}
int ip = 1; while(ip <= n) ar[ip++] = s.nextInt();
computePrimePowers();
int q = s.nextInt();
LVL = new int[n + 1];
dfsTime = 0;
dfs(1, -1);
BLOCK_SIZE = (int) Math.sqrt(dfsTime);
int Q[][] = new int[q][4];
int i = 0;
while(q-- > 0) {
int u = s.nextInt(), v = s.nextInt();
Q[i][0] = lca(u, v);
if (l[u] > l[v]) {
int temp = u; u = v; v = temp;
}
if (Q[i][0] == u) {
Q[i][1] = l[u];
Q[i][2] = l[v];
}
else {
Q[i][1] = r[u]; // left at col1 in query
Q[i][2] = l[v]; // right at col2
}
Q[i][3] = i;
i++;
}
Arrays.sort(Q, new Comparator<int[]>() {
#Override
public int compare(int[] x, int[] y) {
int block_x = (x[1] - 1) / (BLOCK_SIZE + 1);
int block_y = (y[1] - 1) / (BLOCK_SIZE + 1);
if(block_x != block_y)
return block_x - block_y;
return x[2] - y[2];
}
});
solveQueries(Q);
}
System.out.println(sb);
}
static long res;
private static void solveQueries(int [][] Q) {
int M = Q.length;
long results[] = new long[M];
res = 1;
int curL = Q[0][1], curR = Q[0][1] - 1;
int i = 0;
while(i < M){
while (curL < Q[i][1]) check(ID[curL++]);
while (curL > Q[i][1]) check(ID[--curL]);
while (curR < Q[i][2]) check(ID[++curR]);
while (curR > Q[i][2]) check(ID[curR--]);
int u = ID[curL], v = ID[curR];
if (Q[i][0] != u && Q[i][0] != v) check(Q[i][0]);
results[Q[i][3]] = res;
if (Q[i][0] != u && Q[i][0] != v) check(Q[i][0]);
i++;
}
i = 0;
while(i < M) sb.append(results[i++] + "\n");
}
static int visited[];
static int primeCnt[];
private static void check(int x) {
if(visited[x] == 1){
for(int i = 0; i < 7; i++) {
int c = arrPrimes[x][i][1];
int pp = arrPrimes[x][i][0];
if(pp == 0) break;
long tem = res * modI[primeCnt[pp] + 1];
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
primeCnt[pp] -= c;
tem = res * (primeCnt[pp] + 1);
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
}
}
else if(visited[x] == 0){
for(int i = 0; i < 7; i++) {
int c = arrPrimes[x][i][1];
int pp = arrPrimes[x][i][0];
if(pp == 0) break;
long tem = res * modI[primeCnt[pp] + 1];
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
primeCnt[pp] += c;
tem = res * (primeCnt[pp] + 1);
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
}
}
visited[x] ^= 1;
}
static int arrPrimes[][][];
static void computePrimePowers() {
int n = arrPrimes.length;
int i = 0;
while(i < n) {
int ele = ar[i];
int k = 0;
while(ele > 1) {
int c = 0;
int pp = hpf[ele];
while(hpf[ele] == pp) {
c++; ele /= pp;
}
arrPrimes[i][k][0] = pp;
arrPrimes[i][k][1] = c;
k++;
}
i++;
}
}
static int dfsTime;
static int l[] = new int[1000001], r[] = new int[1000001], ID[] = new int[1000001], LVL[], lcaTable[][];
static void dfs(int u, int p){
l[u] = ++dfsTime;
ID[dfsTime] = u;
int i = 1;
while(i < 19) {
lcaTable[i][u] = lcaTable[i - 1][lcaTable[i - 1][u]];
i++;
}
i = 0;
while(i < graph[u].size()){
int v = graph[u].get(i);
i++;
if (v == p) continue;
LVL[v] = LVL[u] + 1;
lcaTable[0][v] = u;
dfs(v, u);
}
r[u] = ++dfsTime;
ID[dfsTime] = u;
}
static int lca(int u, int v){
if (LVL[u] > LVL[v]) {
int temp = u;
u = v; v = temp;
}
int i = 18;
while(i >= 0) {
if (LVL[v] - (1 << i) >= LVL[u]) v = lcaTable[i][v];
i--;
}
if (u == v) return u;
i = 18;
while(i >= 0){
if (lcaTable[i][u] != lcaTable[i][v]){
u = lcaTable[i][u];
v = lcaTable[i][v];
}
i--;
}
return lcaTable[0][u];
}
}
// SIMILAR SOLUTION FOR FINDING NUMBER OF DISTINCT ELEMENTS FROM U TO V
// USING MO's ALGORITHM
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 40005;
const int MAXM = 100005;
const int LN = 19;
int N, M, K, cur, A[MAXN], LVL[MAXN], DP[LN][MAXN];
int BL[MAXN << 1], ID[MAXN << 1], VAL[MAXN], ANS[MAXM];
int d[MAXN], l[MAXN], r[MAXN];
bool VIS[MAXN];
vector < int > adjList[MAXN];
struct query{
int id, l, r, lc;
bool operator < (const query& rhs){
return (BL[l] == BL[rhs.l]) ? (r < rhs.r) : (BL[l] < BL[rhs.l]);
}
}Q[MAXM];
// Set up Stuff
void dfs(int u, int par){
l[u] = ++cur;
ID[cur] = u;
for (int i = 1; i < LN; i++) DP[i][u] = DP[i - 1][DP[i - 1][u]];
for (int i = 0; i < adjList[u].size(); i++){
int v = adjList[u][i];
if (v == par) continue;
LVL[v] = LVL[u] + 1;
DP[0][v] = u;
dfs(v, u);
}
r[u] = ++cur; ID[cur] = u;
}
// Function returns lca of (u) and (v)
inline int lca(int u, int v){
if (LVL[u] > LVL[v]) swap(u, v);
for (int i = LN - 1; i >= 0; i--)
if (LVL[v] - (1 << i) >= LVL[u]) v = DP[i][v];
if (u == v) return u;
for (int i = LN - 1; i >= 0; i--){
if (DP[i][u] != DP[i][v]){
u = DP[i][u];
v = DP[i][v];
}
}
return DP[0][u];
}
inline void check(int x, int& res){
// If (x) occurs twice, then don't consider it's value
if ( (VIS[x]) and (--VAL[A[x]] == 0) ) res--;
else if ( (!VIS[x]) and (VAL[A[x]]++ == 0) ) res++;
VIS[x] ^= 1;
}
void compute(){
// Perform standard Mo's Algorithm
int curL = Q[0].l, curR = Q[0].l - 1, res = 0;
for (int i = 0; i < M; i++){
while (curL < Q[i].l) check(ID[curL++], res);
while (curL > Q[i].l) check(ID[--curL], res);
while (curR < Q[i].r) check(ID[++curR], res);
while (curR > Q[i].r) check(ID[curR--], res);
int u = ID[curL], v = ID[curR];
// Case 2
if (Q[i].lc != u and Q[i].lc != v) check(Q[i].lc, res);
ANS[Q[i].id] = res;
if (Q[i].lc != u and Q[i].lc != v) check(Q[i].lc, res);
}
for (int i = 0; i < M; i++) printf("%d\n", ANS[i]);
}
int main(){
int u, v, x;
while (scanf("%d %d", &N, &M) != EOF){
// Cleanup
cur = 0;
memset(VIS, 0, sizeof(VIS));
memset(VAL, 0, sizeof(VAL));
for (int i = 1; i <= N; i++) adjList[i].clear();
// Inputting Values
for (int i = 1; i <= N; i++) scanf("%d", &A[i]);
memcpy(d + 1, A + 1, sizeof(int) * N);
// Compressing Coordinates
sort(d + 1, d + N + 1);
K = unique(d + 1, d + N + 1) - d - 1;
for (int i = 1; i <= N; i++) A[i] = lower_bound(d + 1, d + K + 1, A[i]) - d;
// Inputting Tree
for (int i = 1; i < N; i++){
scanf("%d %d", &u, &v);
adjList[u].push_back(v);
adjList[v].push_back(u);
}
// Preprocess
DP[0][1] = 1;
dfs(1, -1);
int size = sqrt(cur);
for (int i = 1; i <= cur; i++) BL[i] = (i - 1) / size + 1;
for (int i = 0; i < M; i++){
scanf("%d %d", &u, &v);
Q[i].lc = lca(u, v);
if (l[u] > l[v]) swap(u, v);
if (Q[i].lc == u) Q[i].l = l[u], Q[i].r = l[v];
else Q[i].l = r[u], Q[i].r = l[v];
Q[i].id = i;
}
sort(Q, Q + M);
compute();
}
}
Demo

Why I'm getting different results from GNU g++ and VC++

I'm trying to solve this problem in C++:
"Given a sequence S of integers, find a number of increasing sequences I such that every two consecutive elements in I appear in S, but on the opposite sides of the first element of I."
This is the code I've developed:
#include<iostream>
#include<set>
#include<vector>
using namespace std;
struct Element {
long long height;
long long acc;
long long con;
};
bool fncomp(Element* lhs, Element* rhs) {
return lhs->height < rhs->height;
}
int solution(vector<int> &H) {
// set up
int N = (int)H.size();
if (N == 0 || N == 1) return N;
long long sol = 0;
// build trees
bool(*fn_pt)(Element*, Element*) = fncomp;
set<Element*, bool(*)(Element*, Element*)> rightTree(fn_pt), leftTree(fn_pt);
set<Element*, bool(*)(Element*, Element*)>::iterator ri, li;
for (int i = 0; i < N; i++) {
Element* e = new Element;
e->acc = 0;
e->con = 0;
e->height = H[i];
rightTree.insert(e);
}
//tree elements set up
ri = --rightTree.end();
Element* elem = *ri;
elem->con = 1;
elem->acc = 1;
while (elem->height > H[0]) {
Element* succ = elem;
ri--;
elem = *ri;
elem->con = 1;
elem->acc = succ->acc + 1;
}
rightTree.erase(ri);
elem->con = elem->acc;
leftTree.insert(elem);
sol += elem->acc;
// main loop
Element* pE = new Element;
for (int j = 1; j < (N - 1); j++) {
// bad case
if (H[j] < H[j - 1]) {
///////
Element* nE = new Element;
nE->height = H[j];
pE->height = H[j - 1];
rightTree.erase(nE);
leftTree.insert(nE);
///////
li = leftTree.lower_bound(pE);
long ltAcc = (*li)->acc;
li--;
///////
ri = rightTree.lower_bound(pE);
long rtAcc = 0;
if (ri != rightTree.end()) rtAcc = (*ri)->acc;
ri--;
///////
while (ri != (--rightTree.begin()) && (*ri)->height > H[j]) {
if (fncomp(*ri, *li)) {
(*li)->con = rtAcc + 1;
(*li)->acc = rtAcc + 1 + ltAcc;
ltAcc = (*li)->acc;
--li;
}
else {
(*ri)->con = ltAcc + 1;
(*ri)->acc = ltAcc + 1 + rtAcc;
rtAcc = (*ri)->acc;
--ri;
}
}
while ((*li)->height > H[j]) {
(*li)->con = rtAcc + 1;
(*li)->acc = rtAcc + 1 + ltAcc;
ltAcc = (*li)->acc;
--li;
}
(*li)->con = rtAcc + 1;
(*li)->acc = rtAcc + 1 + ltAcc;
sol += (*li)->acc;
}
// good case
else {
Element* nE = new Element;
nE->height = H[j];
ri = rightTree.upper_bound(nE);
li = leftTree.upper_bound(nE);
rightTree.erase(nE);
if (li == leftTree.end() && ri == rightTree.end()) {
nE->con = 1;
nE->acc = 1;
}
else if (li != leftTree.end() && ri == rightTree.end()) {
nE->con = 1;
nE->acc = 1 + (*li)->acc;
}
else if (li == leftTree.end() && ri != rightTree.end()) {
nE->con = (*ri)->acc + 1;
nE->acc = nE->con;
}
else {
nE->con = (*ri)->acc + 1;
nE->acc = nE->con + (*li)->acc;
}
leftTree.insert(nE);
sol += nE->acc;
}
}
// final step
li = leftTree.upper_bound(*rightTree.begin());
while (li != leftTree.end()) {
sol++;
li++;
}
sol++;
return (int)(sol % 1000000007);
}
int main(int argc, char* argv[]) {
vector<int> H = { 13, 2, 5 };
cout << "sol: " << solution(H) << endl;
system("pause");
}
The main function calls solution(vector<int> H). The point is, when the argument has the particular value of H = {13, 2, 5} the VC++ compiled program give an output value of 7 (which is the correct one), but the GNU g++ compiled program give an output value of 5 (also clang compiled program behave like this).
I'm using this website, among others, for testing different compilers
http://rextester.com/l/cpp_online_compiler_gcc
I've tried to figure out the reason for this wierd behaviour but didn't found any relevant info. Only one post treat a similar problem:
Different results VS C++ and GNU g++
and that's why I'm using long long types in the code, but the problem persists.
The problem was decrementing the start-of-sequence --rightTree.begin()
As I found VC++ and GNU g++ does not behave the same way on above operation. Here is the code that shows the difference, adapted from http://www.cplusplus.com/forum/general/84609/:
#include<iostream>
#include<set>
using namespace std;
struct Element {
long long height;
long long acc;
long long con;
};
bool fncomp(Element* lhs, Element* rhs) {
return lhs->height < rhs->height;
}
int main(){
bool(*fn_pt)(Element*, Element*) = fncomp;
set<Element*, bool(*)(Element*, Element*)> rightTree(fn_pt);
set<Element*, bool(*)(Element*, Element*)>::iterator ri;
ri = rightTree.begin();
--ri;
++ri;
if(ri == rightTree.begin()) cout << "it works!" << endl;
}

To check if a graph is connected using BFS and print MST

I have stored a graph with nodes 1,2,3,4,... in an adjacency list.
I wrote this code to do Breadth First Search (BFS). The BFS works perfect but I don't know what the procedure is to find out if the graph is connected or disconnected and then print the Minimum Spanning Tree of the graph IF it is connected?
An example of the graph which I stored in adjacency list:
1 3 4
2 4
3 1 4
4 2 1 3
And the code for BFS:
int visit[999] = { 0 };
Q.enqueue(0);
while (!Q.isEmpty())
{
y = Q.dequeue();
traverse = g[y];
while (traverse->link != 0)
{
if (visit[traverse->data-1] == 0)
{
visit[traverse->data-1] = 1;
parent = traverse->data;
Q.enqueue(traverse->data-1);
}
traverse = traverse->link;
}
if (visit[traverse->data - 1] == 0)
{
visit[traverse->data - 1] = 1;
parent = traverse->data;
Q.enqueue(traverse->data - 1);
}
}
So I figured it out and put it as a reference for others :)
int parent = 1;
gcounter++;
p = 0;
int visit[999] = { 0 };
int c[999] = { 0 };
int k = 0;
int z = 0;
Queue Q;
Q.enqueue(0);
while (!Q.isEmpty())
{
y = Q.dequeue();
traverse = g[y];
while (traverse->link != 0)
{
if (visit[traverse->data-1] == 0)
{
if (y + 1 != traverse->data)
{
c[z] = y + 1;z++;
c[z] = traverse->data; z++;
}
p++;
visit[traverse->data-1] = 1;
parent = traverse->data;
Q.enqueue(traverse->data-1);
}
traverse = traverse->link;
}
if (visit[traverse->data - 1] == 0)
{
if (y + 1 != traverse->data)
{
c[z] = y + 1; z++;
c[z] = traverse->data; z++;
}
p++;
visit[traverse->data - 1] = 1;
parent = traverse->data;
Q.enqueue(traverse->data - 1);
}
}
if (p < lcounter) //lcounter-> the lines -> total number of nodes
{
writeFile << "The Graph is disconnected" << endl;
}
else
{
writeFile << "The Graph is connected and it's MST is: ";
for (z = 0; c[z+1] != 0; z++)
{
writeFile << "(" << c[z] << "," << c[z + 1] << ") ";
z++;
}
writeFile << endl;
}

find the first longest ascending or descending sub-sequence in a given unsorted sequence by C++

I am writing a C++ program that would find and print the first longest
ascending or descending continuous subsequence for a vector of integers. For example,
given a vector with
4, 2, 1, 2, 3, 4, 3, 5, 1, 2, 4, 6, 5
return 1,2,3,4
My code is as follows:
But, I do not know how to return the first optimal solution.
For example, the above sequence has 1, 2, 4, 6 which is also 4 long.
But, we only need to return 1,2,3,4.
bool findLong(const vector<int> v)
{
if (v.size() <1)
return false;
if (v.size() == 1){
cout << v[0] << endl;
return true;
}
vector::const_iterator itr_left, itr_right;
itr_left = v.begin();
itr_right = v.begin()+1;
bool ascending_flag ;
int counter =0;
if (*itr_right > *(itr_right-1)){
bool ascending_flag = true;
++ascending_counter;
}
else{
bool ascending_flag = false;
++descending_counter;
}
int longest = INT_MIN;
Vector<int>::iterator longest_left = v.begin(), longest_right =v.begin();
++itr_right;
while (itr_right != v.end())
{
if (ascending_flag && *itr_right > *(itr_right-1))
++ascending_counter;
if (!ascending_flag&& *itr_right < *(itr_right-1))
++descending_counter;
if (ascending_flag&& *itr_right < *(itr_right-1))
{
if (ascending_counter > longest )
{
longest = ascending_counter;
longest_left = itr_left;
longest_right = itr_right;
}
itr_left = itr_right;
ascending_counter = 0 ;
ascending_flag = false;
}
if (ascending_flag && *itr_right > *(itr_right-1))
{
if (descending_counter > longest )
{
longest = descending_counter;
longest_left = itr_left;
longest_right = itr_right;
}
itr_left = itr_right;
descending_counter = 0 ;
ascending_flag = true;
}
++itr_right;
}
for_each( longest_left , longest_right, print);
cout << endl;
}
Void print(int i)
{
cout << i << " , " ;
}
Any comments are welcome !
Thanks !
You have lot of typo in your code:
You hide the initialization of ascending_flag
Your length count seems incorrect.
Following should work (as long as there aren't two neighbours with same values).
bool findLong(const vector<int>& v)
{
if (v.empty())
return false;
if (v.size() == 1) {
cout << v[0] << endl;
return true;
}
vector<int>::const_iterator itr_left = v.begin();
vector<int>::const_iterator itr_right = v.begin() + 1;
vector<int>::const_iterator longest_left = itr_left;
vector<int>::const_iterator longest_right = itr_right;
bool ascending_flag = (*itr_right > *(itr_right - 1));
for (++itr_right; itr_right != v.end(); ++itr_right)
{
if (ascending_flag ^ (*itr_right < *(itr_right - 1)))
{
if (itr_right - itr_left > longest_right - longest_left)
{
longest_left = itr_left;
longest_right = itr_right;
}
itr_left = itr_right - 1;
ascending_flag = !ascending_flag;
}
}
for_each(longest_left, longest_right, print);
cout << endl;
return true;
}
Here are some thoughts:
If function is named "findX()", it should return X (say, pointer to the first element of the sequence or NULL, or index of the first element or -1). If function prints X, it should be named "printX()".
It's not clear whether you need ascending or strictly ascending sequence (i.e. is (1, 2, 2, 3) good for you or not).
You overcomplicate things. If you need first sequence, you just use reverse iterators and go from end to beginning, like this (I don't use iterators, but it should be clear how to include them):
int maxLength=1, currentUp=1, currentDown=1; //Last element is sequence of 1 element
size_t result = v.length()-1;
for(size_t i = v.length()-1; i!=0; --i){
if(v[i-1] > v[i]) {
currentDown++; currentUp=0;
} else if(v[i-1] < v[i]) {
currentUp++; currentDown=0;
} else {
//Not clear what should happen, change may be needed
currentUp++; currentDown++;
}
if(maxLength <= max(currentUp, currentDown)) {
result = i-1;
maxLength = max(currentUp, currentDown);
}
}
return result;
Well, for starters, your function will always return true.
if (v.size() <1)
return false;
if (v.size() == 1)
cout << v[0] << endl;
return true;
should probably be
if (v.size() <1) {
return false;
} else if (v.size() == 1) {
cout << v[0] << endl;
return true;
}