Balance ordering parenthesis via Dynamic programing - c++

Hi from the very famous book Code to Crack i come across a question :
Implement an algorithm to print all valid (e.g., properly opened and closed) combinations of n-pairs of parentheses.
Example:
input: 3 (e.g., 3 pairs of parentheses)
output: ()()(), ()(()), (())(), ((()))
#include <iostream>
#include <string>
using namespace std;
void _paren(int l,int r,string s,int count);
void paren(int n)
{
string s="";
_paren(n,n,s,n);
}
void _paren(int l,int r,string s,int count){
if(l<0 || r<0)
return;
if(l==0 && r==0)
cout<<s<<endl;
else{
if(l>0)
{
_paren(l-1,r,s+"(",count+1);
}
if(r>l)
_paren(l,r-1,s+")",count+1);
}
}
int main(){
int n;
cin>>n;
paren(n);
return 0;
}
This is a recursive approach I tried for it . I am pretty sure that we can solve this through dynamic programming as well , as we are already using a lot of value again and again , but I have no idea how to implement this through Dynamic programming I tried tabular bottom up approach but couldnt work out. Please help me out just the basic idea on how to work with this

DP does not really help you. The recursive algorithm is time and space optimal!
In fact, there is a reason not to use DP: the memory requirements! This will be huge.
A better algorithm is to have one character array that you pass in, have the recursive method modify parts of it and print that when needed. I believe that solution is given in the book you mention.

DP can reduce count of traversed states by choosing the optimal solution every call. It also help you to reuse calculated values. There is no calculations, every valid state must be visited, and non-valid states can be avoided by if( ).
I suggest you to implement some another recursion (at least without copying new string object after call, just declare global char array and send it to output when you need).
My idea of recursion is
char arr[maxN]; int n; // n is string length, must be even though
void func(int pos, int count) { // position in string, count of opened '('
if( pos == n ) {
for(int i = 0; i < n; i++)
cout << char(arr[i]);
cout << "\n";
return;
}
if( n-pos-1 > count ) {
arr[pos] = '('; func(pos+1,count+1);
}
if( count > 0 ) {
arr[pos] = ')'; func(pos+1,count-1);
}
}
I didn't checked it, but the idea is clear I think.

Related

Why does my control function do the opposite of what it's supposed to do?

int control(int n, data a[], string cod){
for(int i = 0 ; i<n ; i++){
if(cod == a[i].code)
return i;
}
return -1;
}
Hello, everyone! this is my control function. it's used to check if a code that has been input by a user already exists in the struct. This is what happens in the "input" function:
void input(int &n, data a[]){
string code;
do{
cout<<"\nInput the code: ";
cin>> code;
if((control(n,a,code))>0)
a[n].code=code;
else
cout<<"\nThe code you've input already exists. Please try again.";
}while((control(n,a,code)) == -1);
n++;
}
There are two problems:
everytime i input a code it tells me that it already exists, even though it's my first time.
it doesn't make me try again, even though the code already exists.
Let's start by indenting your code so we can more easily understand what it does:
int control(int n, data a[], string cod) {
for (int i = 0; i < n; i++)
{
if (cod == a[i].code)
return i;
}
return -1;
}
Ah, so it scans through an array, and returns a value greater than or equal to 0 if a string is present, or -1 if it's absent. Then let's consider the code that uses it:
void input(int &n, data a[])
{
string code;
do
{
cout << "\nInput the code: ";
cin >> code;
if ((control(n, a, code)) > 0)
a[n].code = code;
else
cout << "\nThe code you've input already exists. Please try again.";
} while ((control(n, a, code)) == -1);
n++;
}
So this accepts the code if the return value was greater than 0, and otherwise rejects the code as already existing. This is mostly backwards, but not exactly even that.
My suggestion would be to start by defining an enumeration to give meaningful names to the values you're returning. This makes it much easier to keep track of what's going on:
enum { DUPLICATE, UNIQUE };
int control(int n, data a[], string cod) {
for (int i = 0; i < n; i++)
{
if (cod == a[i].code)
return DUPLICATE;
}
return UNIQUE;
}
Now it's much easier to get our condition correct, and much more obvious if we react to it incorrectly:
if (control(n, a, code) == UNIQUE)
a[n].code = code;
else
cout << "\nThe code is a duplicate";
Or, if you prefer to reverse the condition, it's still easy to get correct:
if (control(n, a, code) == DUPLICATE)
cout << "\nThe code is a duplicate";
else
a[n].code = code;
But in particular, if you accidentally get things backwards, it'll be pretty obvious:
if (contro(n, a, code) == UNIQUE)
cout << "\nThe code is a duplicate";
At least to me, the contrast between "UNIQUE" on one line, and "duplicate" immediately below it seems fairly obvious.
Other Points to Consider
I'd advise against having:
using namespace std;
...in your code, as you apparently do right now. This is a bad habit that saves a little typing now, but can lead to considerable grief in the long term.
I'd also look up std::set and std::unordered_set, which can already do (more efficiently) what you're using your data array to do.
If/when you do need something array-like in C++, you probably want to use an std::array or std::vector rather than the built-in array type. They're much more convenient and help prevent quite a few errors.
I'd try to come up with a better name than control for a function that tries to show whether a code is already in use. control is such a generic name, it's almost impossible to guess what it's supposed to accomplish without looking at its content. A good name for a function does a great deal to clarify the code that uses it, and show what you intend that piece of code to accomplish:
std::cin >> new_code;
if (isDuplicate(new_code))
std::cerr << "The code you entered is a duplicate. Please try again\n";
else
codes.add(new_code);
do{
cout<<"\nInput the code: ";
cin>> code;
if((control(n,a,code))>0)
a[n].code=code;
else cout<<"\nThe code you've input already exists. Please try again.";
}while((control(n,a,code))==-1);
I see at least two problems here:
control returns 0 when the element is found at the first position, you check for >0 in the condition
if the loop body sucessfully inserts the element then while((control(n,a,code))==-1); results in an endless loop.
I suggest you to use std::find_if to check if an element is already present. With a std::vector thats:
#include <string>
#include <vector>
#include <algorithm>
struct data {
std::string code;
};
int main() {
std::vector<data> v;
std::string foo = "test";
auto it = std::find_if(v.begin(),v.end(),[foo](auto x){ return x.code == foo;});
bool found = (it == v.end());
}
Also consider to use a std::set if you want a container with unique entries.

String permutation recursion issue

(--This question was answered down below--)
Hey guys so I know this question has been answered in various ways so far on this site but I wanted to see if I could get a hint to my question without getting the blunt answer... sorry if this is redundant!
so... so far my code is this (as the function says, this is supposed to print out every permutation of the string "ABCD" and MUST be done recursively and without the use of STL algorithms):
void printPermutations(string prefix, string remainder)
{
if (remainder.empty())
cout<<prefix<<endl;
else {
for(int i = 0; i<remainder.length(); i++)
{
prefix += remainder[i];
remainder = (remainder.substr(0, i) + remainder.substr(i+1)); //Gets rid of selected char
printPermutations(prefix, remainder); //recursion w/updated values. Problem here?
}
}
}
Where remainder = "ABCD" as a test string. I'm assuming my problem is with the recursive call itself?
So far, the function only prints out the first 3 permutations: ABCD, ABDC, ACBD. I also have a hunch that this could have something to do with the for control since it printed out 3 permutations and 3 would be less than the string's length of 4? I don't know. I just started learning recursion and it's really hard for me to figure out how to implement recursive calls properly.
The problem is that you're modifying both strings in the loop, so prefix grows and remainder shrinks.
That is, you want the "top-level" call to iterate through A/BCD, B/ACD, C/ABD, and D/ABC, but you're iterating through A/BCD, AB/CD, ABC/D, and ABCD/empty.
Don't modify the strings, just pass the values you want to the recursion:
void printPermutations(string prefix, string remainder)
{
if (remainder.empty())
cout<<prefix<<endl;
else {
for(int i = 0; i<remainder.length(); i++)
{
printPermutations(prefix + remainder[i],
remainder.substr(0, i) + remainder.substr(i+1));
}
}
}
Or use "fresh" variables if you want a more "step-by-step" look:
void printPermutations(string prefix, string remainder)
{
if (remainder.empty())
cout<<prefix<<endl;
else {
for(int i = 0; i<remainder.length(); i++)
{
string thisPrefix = prefix + remainder[i];
string thisRemainder = remainder.substr(0, i) + remainder.substr(i+1);
printPermutations(thisPrefix, thisRemainder);
}
}
}
Please consider using the stl algorithm next_permutation for the job. The code in your case is than:
#include <algorithm>
#include <string>
#include <iostream>
int main()
{
std::string s = "ABCD";
std::sort(s.begin(), s.end());
do {
std::cout << s << '\n';
} while(std::next_permutation(s.begin(), s.end()));
}
If you need to, you can write a wrapper around this snippet.

How can I optimize my code for large number of strings on input

I passed 4 tests on my university compiler and the problem is the 5th one. Time limit is 1second for each test. How can I optimize this code, maybe there is a better option for sorting if I compare strings? My code:
#include <iostream>
#include <string.h>
using namespace std;
void qsort(string &tab, int min, int max)
{
if(min<max)
{
int min_min = min;
for(int i=min+1;i<=max;i++)
{
if(tab[i]<tab[min])
{
swap(tab[++min_min],tab[i]);
}
}
swap(tab[min],tab[min_min]);
qsort(tab,min,min_min-1);
qsort(tab,min_min+1,max);
}
}
bool sprawdz(string tab,string tab2)
{
for(int i=0;i<tab.length();i++)
{
if(tab[i]!=tab2[i])
{
return false;
break;
}
}
return true;
}
int main()
{
string tablica1, tablica2;
int ile;
scanf("%d",&ile);
for(int i=0;i<ile;i++)
{
cin>>tablica1>>tablica2;
qsort(tablica1,0,tablica1.length()-1);
qsort(tablica2,0,tablica2.length()-1);
if(tablica1==tablica2)
{
printf("TAK\n");
}
else
{
printf("NIE\n");
}
}
return 0;
}
Only information it thrown is min = 25177
max = 25978
so these numbers are quite large. Any ideas? Task is to check if words are anagrams.
maybe there is a better option for sorting if I compare strings?
My favourite tip: The optimal way to do something is to not do it ;)
You do not have to sort the strings to check if they are anagrams. Order does not matter for anagrams, so why sort them?
Sorting is typically O(n log n), while simply counting the frequency of characters is O(n). To count characters you can use a std::unordered_map, or if that is not allowed use an array of counters. Traverse the strings to count occurences of each character, then compare the arrays of counters.
PS: You should also check if the size of the strings is the same before applying any further logic.

Modifying a recursive string reverse function

I am doing some recursive exercises. The previous one was to make a reverse() function for a string which basically removes the first character and then combines the solution. I managed to do that, here is the source code (the entire source) The current task is to modify this function (the following exercise in the book) by adding a helper function which reverses a substring of the string. At this moment I am stuck at this. It is my understanding that you use helper functions when you need to pass additional arguments or something and this function takes none so I really have no idea how to approach this problem. Help appreciated.
#include <iostream>
#include <string>
using namespace std;
void reverse(string& text)
{
if (text.length() == 0)
{
return;
}
if (text.length() == 1)
{
return;
}
else
{
string firstLetter = text.substr(0,1);
text = text.substr(1, text.length()-1);
reverse(text);
text += firstLetter;
}
}
int main()
{
string a = "tyu";
reverse(a);
cout << a << endl;
return 0;
}
A guy suggested to use parameters, ect, this is my try with it:
#include <iostream>
#include <string>
using namespace std;
//is actually doing the hard work
void reverse1(string& input, int a, int b)
{
// base case
if( a >= b)
{
return;
}
//swap the characters
char tmp;
tmp = input[a];
input[a] = input[b];
input[b] = tmp;
//create the boundries for the new substring
a++;
b--;
//call the function again
reverse1(input, a, b);
}
// sets the parameters and calls the helper function
void strreverse(string& input)
{
reverse1(input, 0, input.length()-1);
}
int main()
{
cout << "Please enter the string which you want to be reversed:";
string a;
cin >> a;
strreverse(a);
cout << a << endl;
return 0;
}
The goal is probably to avoid creating all of the intermediate substrings. The helper function will take iterators, or a start and end index in addition to the string begin reversed.
Try to implement reversing so that there is only one instance of std::string (i.e. work with it as with an array). Then you will need a helper function with additional parameters (at least one parameter - which index to reverse now).
I would implement reverse here as series of exchanges: a[0] <-> a[n-1], a[1] <-> a[n-2] etc. where n is length of the string.
You can define a helper function that takes a start and an end index of the substring which it will reverse.
The function should exchange the element at the start index with that at the end index IFF the difference between the start and the end indices is 1. Otherwise, it places a recursive call to itself by decrementing the end index and incrementing the start index. You will need to keep check on the condition if the start and end index become same though.

Constructor issue <Unable to read memory>

I have to create a class Histogram and make operations on this class. The input can be one dimensional array or a two dimensional array. The problem appears when i convert the array into a matrix. This what i have tried so far. The error is <Unable to read memory>
histrogram.h
#ifndef HISTOGRAM_H
#define HISTOGRAM_H
#include<iostream>
class Histogram
{
private:
int** matrix;
int lines;
void SortMatrix();
public:
Histogram(){ }
Histogram(int elements[], int elementsNr);
Histogram(int** m, int l);
void Print();
};
#endif
historgram.cpp
#include"histogram.h"
using namespace std;
Histogram::Histogram(int** m, int l)
{
matrix=m;
lines=l;
SortMatrix();
}
Histogram::Histogram(int elements[], int elementsNr)
{
lines=0;
//initialize matrix : elementrNr lines and 2 columns
int** matrix=new int*[elementsNr];
for(int i=0;i<elementsNr;i++)
{
matrix[i]=new int[2];
matrix[i][0]=INT_MIN;
matrix[i][1]=INT_MIN;
}
//search each element from the array in the matrix
bool found=false;
for(int i=0;i<elementsNr;i++)
{
found=false;
for(int j=0;j<elementsNr;j++)
{
//the element was found in the matrix ( on the first column )
if(matrix[j][0] == elements[i])
{
matrix[j][1]++;
found=true;
break;
}
}
if(!found)
{
matrix[lines][0]=elements[i];
matrix[lines][1]=1;
lines++;
}
}
SortMatrix();
}
void Histogram::SortMatrix()
{
bool flag=true;
int temp;
for(int i=0;(i<lines) && flag;i++)
{
flag=false;
if(matrix[i+1][0]>matrix[i][0])
{
temp=matrix[i][0];
matrix[i][0]=matrix[i+1][0];
matrix[i+1][0]=temp;
flag=true;
}
}
}
void Histogram::Print()
{
for(int i=0;i<lines;i++)
{
cout<<matrix[i][0]<<" : " <<matrix[i][1]<<endl;
}
}
main.cpp
#include"histogram.h"
#include<iostream>
using namespace std;
int main()
{
int arr[]={6,7,3,1,3,2,4,4,7,5,1,1,5,6,6,4,5};
Histogram h(arr,17);
h.Print();
}
Here
int** matrix=new int*[elementsNr];
replace with
matrix=new int*[elementsNr];
becausematrix is already a member variable. You are creating a new temporary variable double pointer named matrix and allocating memory to it rather than your member variable matrix
A couple of people have already given you advice about how to fix some of the problems with this code. I'll give slightly different advice that may initially seem a bit brutal by comparison, but I'll try to demonstrate how it's honestly useful rather than nasty.
I would throw out your existing code with the possible exception of what you have in main, and start over, using an std::map. What you're doing right now is basically trying to re-create the capabilities that std::map already provides (and even when your code is fixed, it's not doing the job as well as std::map does right out of the box).
Using map, your whole program comes out to something like this:
std::ostream &operator<<(std::ostream &os, std::pair<int, int> const &d) {
return os << d.first << " : " << d.second;
}
int main() {
std::map<int, int> h;
for (int i=0; i<17; i++)
++h[arr[i]];
std::copy(h.begin(), h.end(),
std::ostream_iterator<std::pair<int, int> >(std::cout, "\n"));
return 0;
}
If you want to maintain virtually the same interface as your histogram class provided, it's pretty easy to do that -- the for loop goes into the constructor, the copy into print (and SortMatrix disappears, because a map is always sorted).
By doing this, you change from an O(N2) algorithm to an O(N log N) algorithm. The bugs others have pointed out disappear completely, because the code that contained them is no longer needed. The only real disadvantage I can see is that the result will probably use a bit more memory -- it uses a balanced tree with individually allocated nodes, which is likely to introduce a fair amount of overhead for nodes that only contain 2 ints (and a bit for balancing). I can't quite imagine worrying about this though -- long before you have enough nodes for the memory usage to become significant, you have way too many to present to even consider presenting to the user.
#mathematician1975 already provided an answer for the main problem. There's another bug in SortMatrix(): you only swap the elements of the first column, therefore after sorting, the counts (in the second column) will not be correct anymore. You'll have to insert
temp=matrix[i][1];
matrix[i][1]=matrix[i+1][1];
matrix[i+1][1]=temp;
to get it working.