Another approach for finding longest increasing subsequence - c++

I am aware that there are many algorithms for finding longest increasing subsequence, but the algorithms using DP all have this is common - they recurse/ dynimacally calculate longest subsequence "ENDING" at a particular element of the array.
I wrote a solution which resurses taking longest subsequence "starting" at a particular array, which seems to work fine too.
#include<iostream>
using namespace std;
#define boostio ios_base::sync_with_stdio(0);
int n;
int a[100000];
int t[100000] = {-1};
int lis(int i){
if(t[i]!= -1){
return t[i];
}
if(i == n){t[i] = 1; return 1;
}
for (int x = i+1; x <= n ; ++x)
{
if(a[x] > a[i] and 1 + lis(x) > t[i]){
t[i] = 1 + lis(x);
//return t[i];
}
}
if(t[i] != -1){
return t[i];
}
t[i] = 1; return 1;
}
int main(){
boostio;
cin >> n;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
}
fill(t, t + n+2 ,-1);
Int m = 0;
for (int i = 1; i <= n; ++i)
{
//cout << i << " " << lis(i) << endl;
if(lis(i) >m) m= lis(i);
}
cout << m;
return 0;
}
I am wondering, is this in any way worse than if we recurse on "last element" of subsequence instead of the first. They both appear to be order n square algorithms to me, so why isnt this algorithm more circulated. To me it seems more intuitive. Am I missing something?

Related

Count of Maximum , Passing Test cases but WA

Getting error in this code, even though it passed the basic test cases. But still, it gives the wrong answer.
Cannot find the test case where it fails, Solution to Codechef Count of maximum problem. I think a part of the code is making it fail for a certain test case(s).
Can anyone help me find the error in this code, please?
#include <bits/stdc++.h>
using namespace std;
int main()
{
int k;
cin >> k;
for (int j = 0; j < k; j++)
{
int n;
cin >> n;
int a[n];
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int maxCount = 0;
int number;
int index = 0;
for (int i = 0; i < n; i++)
{
int count = 0;
for (int l = 0; l < n; l++)
{
if (a[i] == a[l])
{
count++;
if (count > maxCount)
{
maxCount = count;
index = i;
}
if (count == maxCount) {
(a[i] > a[index]) ? number = a[index] : number = a[i];
}
}
}
}
cout << number << " " << maxCount << endl;
}
}
Your number variable is redundant. You need to track theindex of the elements in the array.
That means, change this line
(a[i] > a[index]) ? number = a[index] : number = a[i];
to
(a[i] > a[index]) ? index = index : index = i;
and print
std::cout << a[index] << " " << maxCount << std::endl;

Prime Numbers Up To A Number

Im really new to C++ and im working through the book Programming: Principles and Practice Using C++. Were working on the problem to find all prime numbers between 1 - user given number. Now I got that part down. I now understand that the sqrt(i) would make the loop shorter but, Im not sure what to check for to see if its a prime or not in my if - else statements.
#include<vector>
#include<iostream>
#include<cmath>
using namespace std;
int main(){
vector<double> prime_numbers;
double num;
cout << "Please enter a number so we can find the primes for it: " << flush;
cin >> num;
for (int i = 2; i <= num; i++) {
for (int j = 2; j <= i; j++) {
// cout << sqrt(i) << "\t";
// Check to see if Value of i is incremented correctly
// Check to see if value of j is incremented properly before returnign to i
//cout << i <<"\t" << j << endl;
if (j == i) {
prime_numbers.push_back(i);
}
if (i % j == 0) {
break;
}
}
}
for (double x : prime_numbers)
cout << x << " | ";
return 0;
}
A very efficient way to find the prime numbers from 0 to n is using the sieve of Eratosthenes, there are many ways to do it, here is an example:
vector<bool> v(n, true);
v[0] = v[1] = false;
for (int i = 2; i*i < n; i+= 2){
if (v[i]) {
for (int k = i*i; k < n; k += i) {
v[k] = false;
}
if (i == 2)i = 1;
}
}
for(auto i = 0; i < n; ++i)
if(v[i])cout << i << ' ';
cout << endl;
The difference is that your previous primality condition ā€“ i == jā€“ is no longer true.
It is true exactly when you have examined every number from 2 to i, but with the sqrt(i) limit, you're exiting the loop much earlier.
I think the simplest change is to introduce a variable and move the push_back outside the loop (this works with either loop condition):
for (int i = 2; i <= num; i++) {
bool isPrime = true; // Assume 'i' is prime until proven wrong.
for (int j = 2; j <= sqrt(i); j++) {
if (i % j == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
prime_numbers.push_back(i);
}
}
That is, first decide whether something is the case, then do something with that information.
This is a useful design in very many cases.
For instance,It makes it much easier to move the primality check into a function:
bool isPrime(int x) { /* something */ }
// ...
for (int i = 2; i <= num; i++) {
if (isPrime(i)) {
prime_numbers.push_back(i);
}
}

Counting number of copying and comparisons in heapsort and insertation sort

I want to count how many times does algorithm makes comparisons and how many times algorithm makes copying.
#include <stdio.h>
#include <random>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <time.h>
void generuoti(int _N, const char *_file);
void nuskaityti(const char *_file);
int ps = 0;
int ks = 0;
void heapify(double arr[], int n, int i)
{
int largest = i; // Initialize largest as root
int l = 2 * i + 1; // left = 2*i + 1
int r = 2 * i + 2; // right = 2*i + 2
// If left child is larger than root
if (l < n && arr[l] > arr[largest])
largest = l;
ps+=1;
// If right child is larger than largest so far
if (r < n && arr[r] > arr[largest])
largest = r;
ps += 1;
// If largest is not root
if (largest != i)
{
std::swap(arr[i], arr[largest]);
ps += 1;
ks += 1;
// Recursively heapify the affected sub-tree
heapify(arr, n, largest);
}
}
// pagr funkcija haep sortui
void heapSort(double arr[], int n)
{
// Build heap (rearrange array)
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
// One by one extract an element from heap
for (int i = n - 1; i >= 0; i--)
{
// Move current root to end
std::swap(arr[0], arr[i]);
ks+=1;
// call max heapify on the reduced heap
heapify(arr, i, 0);
}
}
void insertion_sort(double arr[], int n)
{
int i, key, j;
for (i = 1; i < n; i++)
{
key = arr[i];
j = i - 1;
ks+=1;
while (j >= 0 && arr[j] > key)
{
arr[j + 1] = arr[j];
j = j - 1;
ks+=1;
ps+=1;
}
arr[j + 1] = key;
ks+=1;
}
}
using namespace std;
double *Data;
double* A;
double* B;
double N;
int main()
{
srand(time(NULL));
cout << "Generuojame atsitktinius duomenis" << endl;
generuoti(20000, "duom.txt");
cout << "Nuskaitome duomenis" << endl;
nuskaityti("duom.txt");
A = new double[(int)N];
B = new double[(int)N];//jeigu algoritmui reikia papildomo masyvo
for (int i = 0; i < N; i++) {
A[i] = Data[i];
}
cout << "Pradine skaiciu seka:" << endl;
for (int i = 0; i < N; i++)
cout << A[i] << " ";
cout << endl;
//
insertion_sort(A, N);
//heapSort(A, N);
//truksta veiksmu sk
cout << "Surusiuota skaiciu seka:" << endl;
for (int i = 0; i < N; i++)
cout << A[i] << " ";
cout << endl;
cout << "Kopijavimu skaicius " << ks << endl;
cout << "Palyginimu skaicius " << ps << endl;
system("pause");
return 0;
}
void generuoti(int _n, const char *_file) {
ofstream os(_file);
os << _n << endl;
for (int i = 0; i<_n; i++)
os << " " << 500+ (double)(rand() % 3001) ;
os.close();
}
void nuskaityti(const char *_file) {
ifstream is(_file);
if (is.fail()) {
cout << "Failo nera" << endl;
exit(1);
}
is >> N;
Data = new double[(int)N];
for (int i = 0; i < N; i++) {
is >> Data[i];
}
}
This is my code, and ps - is equal to a number of comparisons, and ks - is equal to number of copying. I want to ask if I counted all comparisons and all copying in the algorithms? Thanks for answers.
No
if (l < n && arr[l] > arr[largest])
largest = l;
ps+=1;
There are two problems here. Assuming you are talking about double comparisons (rather than integer), the comparison may or may not occur.
Secondly your indentation is deeply misleading. (You always increment.)
You need
if (l < n) {
ps++; // About to compare
if (arr[l] > arr[largest])
largest = l;
}
There are probably other errors, but it is impossible to tell because I can't read your language, so the printed text, comments, and names are meaningless.
Given you are writing in C++, I would write a class with operator <() and operator =, and a copy constructor, and instrument those. That way you cannot possibly get it wrong.

This Code is giving the wrong output can't figure out where I made a mistake

The code should display the number of times maximum number in the array has occurred so for the following input (3,2,1,3) the output should be '2' as '3' is the maximum number and occurs twice. I wanted to use functions, I know there is an easier way to solve it but i just want to know the problem in my code:-
#include<iostream>
using namespace std;
int frequency(int n, int a[]) {
int j=0,max,count=0;
max = a[j];
while(j<n){
if(a[j+1]> max){
max = a[j+1];
}
j++;
}
int seen[n];
for(int i = 0; i < n; i++)
seen[i] = 0;
for(int i = 0; i < n;i++) {
if(seen[i] == 0) {
int count = 0;
for(int j = i; j < n;j++)
if(a[j] == a[i] && a[j] == max)
count += 1;
seen[j] = 1;
}
}
return count;
}
int main() {
int i,n;
cin >> n;
int a[n];
for(i = 0; i < n; i++){
cin >> a[i];
}
int result = frequency(n, a);
cout << result << endl;
return 0;
}
For starters the C++ Standard does not support Variable Length Arrays. So instead of an array you should use some container as for example std::vector<int>.
Moreover the program has undefined behavior because at least in this loop
while(j<n){
if(a[j+1]> max){
max = a[j+1];
}
j++;
}
there is an attempt to access memory beyond the array in the expression a[j+1].
And at last the function always returns 0 because the variable count in the outermost scope of the function is set to zero and is never changed.
A general approach can be written using iterators.
For example
#include <iostream>
#include <iterator>
#include <vector>
template <typename InputIterator>
size_t count_maximum_value( InputIterator first, InputIterator last )
{
size_t count = 0;
if ( first != last )
{
++count;
typename std::iterator_traits<InputIterator>::value_type max = *first;
while ( ++first != last )
{
if ( max < *first )
{
max = *first;
count = 1;
}
else if ( not ( *first < max ) )
{
++count;
}
}
}
return count;
}
int main()
{
size_t n = 0;
std::cout << "Enter the number of integers: ";
std::cin >> n;
if ( n )
{
std::vector<int> v( n );
std::cout << "Enter " << n << " integers: ";
for ( size_t i = 0; i < n; i++ ) std::cin >> v[i];
std::cout << "The maximum value is encountered "
<< count_maximum_value( v.begin(), v.end() )
<< " time(s)"
<< std::endl;
}
return 0;
}
The program output might look the following way
Enter the number of integers: 4
Enter 4 integers: 3 2 1 3
The maximum value is encountered 2 time(s)
You are comparing a[j+1] with max. I suggest you use a[j]. You seem to be skipping the first number in your input.
Start with count = 1 instead of count = 0 and delete the redeclaration of count in the loop.
You're starting with 0, then you add 1 when you find the second entry that matches it. That's why you're off by one.
Check the comments
#include<iostream>
using namespace std;
int frequency(int n, int a[]) {
int j=0,max,count=0;
max = a[j];
while(j<n){
if(a[j]> max){ // 1. j+1 crosses lenth of array
max = a[j];
}
j++;
}
int seen[n];
for(int i = 0; i < n; i++)
seen[i] = 0;
for(int i = 0; i < n;i++) {
if(seen[i] == 0) {
//int count = 0; //2. re declaration and you are not returning this
//for(int j = i; j < n;j++) //3. No need of extra loop it make count extra because you are starting at j=i
//if(a[j] == a[i] && a[j] == max)
if(a[i] == max)
count += 1;
seen[j] = 1;
}
}
return count;
}
int main() {
int i,n;
cin >> n;
int a[n];
for(i = 0; i < n; i++){
cin >> a[i];
}
int result = frequency(n, a);
cout << result << endl;
return 0;
}

UVa online judge - 3n + 1 - wrong answer?

Here's my C++ code for the 3n+1 problem from UVA online judge which runs fine here, but each submission is judged as the wrong solution. I believe it has something to do with input, or output formatting. I just don't know exactly what the issue is. Could anyone help me investigate this issue?
#include <iostream>
using namespace std;
int main(){
int i, j, ori, orj, complexity = 0;
while(!cin.eof()){
cin >> i >> j;
ori = i;
orj = j;
if (i > j){
int temp = i;
i = j;
j = temp;
}
for (int k = i; k <= j; k++){
int c = 1;
int n = k;
do{
c++;
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
} while (n != 1);
if (c > complexity)
complexity = c;
}
cout << ori << " " << orj << " " << complexity << endl;
}
return 0;
}
Each submission has come under the time limit, and when I debug i get correct outputs.
!cin.eof() is not a good way to determine when to exit from the loop.
Try changing
while(!cin.eof()){
cin >> i >> j;
to
while(cin >> i >> j){
You have to clear value of complexity variable for every new input numbers. Your code also doesn't handles correctly values of i and j equal to 1. You have to add special condition and not to run the loop in this case. So this it the whole code change:
int main() {
int i, j, ori, orj, complexity;
while (!cin.eof()) {
complexity = 0;
cin >> i >> j;
ori = i;
orj = j;
if (i > j) {
int temp = i;
i = j;
j = temp;
}
if (j > 1) {
for (int k = i; k <= j; k++) {
int c = 1;
int n = k;
do {
c++;
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
} while (n != 1);
if (c > complexity)
complexity = c;
}
} else {
complexity = 1;
}
cout << ori << " " << orj << " " << complexity << endl;
}
return 0;
}