Why am I getting string reversal wrong with a trailing space character? - c++

I am unable to get why there is a space and it is getting me wrong.
Below is the code I wrote for the solution
Why there is blank space char at the end of the string at the end even after reversing my string.
Question
class Solution {
public:
string minRemoveToMakeValid(string s) {
string str = "";
int n = s.length();
int open=0;
for(int i=0;i<n;i++){
if(s[i]=='('){
open++;
}else if(s[i]==')'){
open--;
if(open<0){
open=0;
continue;
}
}
str+=s[i];
}
open=0;
string s2="";
for(int i=n-1;i>=0;i--){
if(str[i]==')'){
open++;
}else if(str[i]=='('){
open--;
if(open<0){
open=0;
continue;
}
}
s2=s2+str[i];
}
reverse(s2.begin(),s2.end());
return s2;
}
};
Leetcode Submission getting wrong

The length of str may be less than one of s, but you are using the length of s while iterating within str. You must use correct length.
string s2="";
n = str.length(); // add this
for(int i=n-1;i>=0;i--){

Related

Permutation of a string is failing for string having duplicate character

I am trying to understand how backtracking works. I am working on permutation of a string.
class Solution {
public:
void permute(string s,int count[], string res, int level, vector<string> &perS)
{
if( level == s.size())
{
//cout<<res<<endl;
perS.push_back(res);
return;
}
int i;
for(i=0; i<s.size(); i++)
{
if(count[i]==0)
{
continue;
}
res += s[i];
count[i]--;
permute(s, count, res, level+1, perS);
count[i]++;
//this line is problem I think?? how to handle if s1 contains duplicates??
res.erase(res.end()-1);
}
}
bool checkInclusion(string s1, string s2) {
map<char, int> mp;
for(int i=0; i<s1.size(); i++)
{
mp[s1[i]]++;
}
int *count = new int[mp.size()];
set<char> us;
//to generate the count array of all the characters
for(int i=0; i<s1.size(); i++)
{
us.insert(s1[i]);
}
auto it = us.begin();
for(int i=0; i<mp.size(); i++)
{
count[i] = mp[*it++]++;
}
string res;
vector<string> perS;
permute(s1, count, res, 0, perS);
//check if s2 contains in pers;
for(string x:perS)
{
if(s2.find(x)!=string::npos)
return true;
}
return false;
}
};
The above code works when I pass s1 as "helo" but give stackoverflow error if it has duplicates in it ex. "hello".
The algorithm I am trying to understand is very simple. we select a character from the string and traverse the other characters. once we reach the end we backtrack and check other options.
I tried but not able to understand why it fails for string having duplicates.
https://www.youtube.com/watch?v=nYFd7VHKyWQ&t=1346s
I am trying the same algo explained in the above url, but I am trying to code it in cpp language.
I would really appreciate any input on this. This is my first question so pardon me for any error. it will help me visualise the recursive flow for backtracking problem.

Vector of String not working when assiging strings using equals operator in C++

I am trying this Code
string str;
ll size=0;
vector<string> finalStr;
while(getline(cin, str))
{
for(int i=0; i<str.length(); i++)
{
if(count)
{
if(str[i]=='"')
{
str.erase(i, 1);
str.insert(i,"``");
count = false;
}
}
if(!count)
{
if(str[i]=='"')
{
str.erase(i, 1);
str.insert(i,"''");
count = true;
}
}
}
finalStr[size++] = str;
}
This Code doesn't work. I need reason why it is working when I am using finStr.push_back(str).
Above Code is working good Till I Assigned the input string to my vector of String using equals operator.

Reverse a string. Not sure why this logic is wrong. C++

I am a beginner in solving algorithmic questions. Until now, I have only self-taught coding. So, I am not sure about the proper conventions.
I was trying to solve a question to reverse a string.There is some problem with the code but I am not sure what it is after debugging step-by-step.
class Solution {
public:
string reverseString(string s) {
int n = s.length();
string reverse;
for (int i=0;i<s.length();i++)
{
reverse[i] = s[n-1];
n=n-1;
}
return reverse;
}
};
Input: "Hello"
Output needed: "olleh"
My output: "olleh " (extra space)
Input: A man, a plan, a canal: Panama
Output: No output
I searched online for solutions. There were related to pointers. It would be great if someone helped me understand why this logic doesn't work and why using pointers is a better idea.
ALREADY GIVEN. CANNOT CHANGE:
string stringToString(string input) {
assert(input.length() >= 2);
string result;
for (int i = 1; i < input.length() -1; i++) {
char currentChar = input[i];
if (input[i] == '\\') {
char nextChar = input[i+1];
switch (nextChar) {
case '\"': result.push_back('\"'); break;
case '/' : result.push_back('/'); break;
case '\\': result.push_back('\\'); break;
case 'b' : result.push_back('\b'); break;
case 'f' : result.push_back('\f'); break;
case 'r' : result.push_back('\r'); break;
case 'n' : result.push_back('\n'); break;
case 't' : result.push_back('\t'); break;
default: break;
}
i++;
} else {
result.push_back(currentChar);
}
}
return result;
}
int main() {
string line;
while (getline(cin, line)) {
string s = stringToString(line);
string ret = Solution().reverseString(s);
string out = (ret);
cout << out << endl;
}
return 0;
}
As you create reverse, you have to pass the length of the string as an argument, else the created string will be of size 0. This could look like this:
string reverseString(string s) {
int n = s.length();
string reverse(n,'0');
for (int i=0;i<s.length();i++)
{
reverse[i] = s[n-1];
n=n-1;
}
return reverse;
}
Reversing a string is trivial. Just construct a new one from the reverse iterators:
std::string reverse_str(s.rbegin(), s.rend());
or
std::string reverse_str(s.crbegin(), s.crend());
Here's how I would write your function:
string reverseString(const string& s) {
return {s.crbegin(), s.crend()};
}
Try this out
class Solution {
public:
string reverseString(string s) {
//cout<<"inside func";
int n = s.length();
cout<<n<<endl;
char reverse[sizeof(char)*n];// reverse stores the reverse of original string s
int i= 0;
for ( i=0;i<s.length();i++)
{
reverse[i] = s[n-i-1];
}
return reverse;
}
}
int main()
{
string s,r;
Solution sol;
s= "hello";
r= sol.reverseString(s);
cout<<r<<endl;
cout<<r.length()<<endl;
return 0;
}
when i= 0, n-i-1= n-1 which is the last element of the original string s. So the first element of the reverse string is the last element of s. Next i becomes i+1 i.e 1. This time second element of the reverse string is the last but one element in string s. This procedure is repeated till i < s.length(). The element to get copied is for index i= n-1 and n becomes n-(n-1)-1= 0, so the last element of reverse string is the first element of s. After this the loop exists. No additional extra characters are added.

Debug my reimplementation of strtok and split

I'm supposed to be writing code that takes a string of comma separated values without spaces (ex. my,name,is,jack). First we had to write a function
string nextstring(string str, int start_index)
that returns a single "value" from your initial string depending on the start index. The second part of the problem was to write a function
int split(string str, string a[], int max_size)
that will identify all the values in the initial string and put them in a string array and then return the total number of values stored in the array; i.e. if you had initially input my,name,is it would return 3.
My function never returns the correct value and whatever it returns changes depending on what the length of the words are.
#include <iostream>
#include <string>
using namespace std;
string nextstring(string str, int start_index);
int split(string str, string a[], int max_size);
int main()
{
string str;
int cnt;
string a[100];
cout<< "what is your string" << endl;
getline(cin, str);
cnt= split(str, a, 100);
cout << "There are " << cnt << " values in this string" << endl;
for(int i=0; i<cnt; i++)
{
cout << a[i] << endl;
}
return 0;
}
string nextstring(string str, int start_index)
{
string ans;
if(str[start_index] == ',' || str[start_index] == '\0')
{
ans=" ";
}
else{
ans=str[start_index]+nextstring(str, start_index+1);
}
return ans;
}
int split(string str, string a[], int max_size)
{
int j=0;
int ans=0;
double k=0;
while(j<max_size)
{
a[j]= nextstring(str,k);
string check=a[j];
if(isalpha(check[0])!= 0)
{
ans++;
}
k=k+a[j].length();
j++;
}
return ans;
}
It seems that your problem is that while(j<max_size){...} leads to j being incremented up to max_size. The line a[j]= nextstring(str,k); is at some points reading values that are outside your string which is really bad!
Replacing while(j<max_size){...} by while(j<max_size && k<str.length()){...} seems to be enough to make your code work!
Apart from that:
k has no reason to be a double! It should be an int (or something similar).
Since you are already using string, you should also learn to use vector. split is better written as:
int split(string str, vector<string> &a, int max_size)
{
int ans=0;
int k=0;
while(k<str.length())
{
string next = nextstring(str,k);
if(isalpha(next[0])!= 0)
{
ans++;
a.append(next);
}
k += next.length();
}
return ans;
}
The problem in your approach is to identify the end of the string, as there is no null terminator in a c++ string. Consider to update nextstring() to look for the end of string in a different manner:
string nextstring(string str, int start_index)
{
...
if(start_index == str.size() || str[start_index] == ',' ) //<===
{
ans=" ";
}
...
}
online demo
Additional recommendation
Note that it is not very nice to return a blank string when in reality it should be empty to reflect its real value (e.g. ",,"). You have no choice because otherwise you would have no mean in the calling function, to determine that the end of string was reached. But the consequence is thar all your strings have a trailing blank.
When you call recursively the function adding char to build the return string, you risk to have a considerable overhead. You could consider avoiding this, by replacing the else part:
ans=str.substr(start_index, str.find(',', start_index+1)-start_index);
However, as you have no trailing blank anymore, you need to adapt split() so to adapt its way to count the total number of chars parsed:
k=k+a[j].length()+1; // +1 because there's no longer a trailing blank.
Online demo

C++ reading string segmentation fault

I am writing a program that will input an alphabetic message, and use the class to build the morse code string, and then output the string. I have written all the method and the program compiles fine. However when I enter the temp string and hit return. I am given a segmentation fault. I can't seem to find the problem. If anyone can see what the problem is I would greatly appreciate your help. Thanks.
#include <string>
#include <vector>
#include <fstream>
using namespace std;
class Code
{
public:
Code(); // Default constructor - loads and uses morse code
string decode(vector< string> message); // decodes a message
string encode(vector<char> message); // encodes a message
private:
vector<string> codewords; // this is a codeword vector parallel to A-Z
vector<char> alpha; // this is the vector for A-Z
vector<char> alphacode(); // function builds the vector alpha - A B C etc.
vector<string> morsecode(); // function builds the vector codewords containing morse code
char decode(string c); //returns the character for the codeword c.
string encode(char c);
};
Code::Code() {
alpha = alphacode();
codewords = morsecode();
}
string Code::decode(vector< string> message) {
string temp;
for (int i=0; i < message.size(); i++) {
temp += decode(message[i]);
}
return temp;
}
string Code::encode(vector<char> message)
{
string temp;
for (int i=0; i<message.size(); i++)
{
temp+=encode(message[i]);
}
return temp;
}
vector<string> Code::morsecode()
{ // This function returns a vector containing the morse code
vector<string> temp(28);
temp[0] =".-";
temp[1] ="-...";
temp[2] ="-.-.";
temp[3] ="-..";
temp[4] =".";
temp[5] ="..-.";
temp[6] ="--.";
temp[7] ="....";
temp[8] ="..";
temp[9] =".---";
temp[10] ="-.-";
temp[11] =".-..";
temp[12] ="--";
temp[13] ="-.";
temp[14] ="---";
temp[15] =".--.";
temp[16] ="--.--";
temp[17] =".-.";
temp[18] ="...";
temp[19] ="-";
temp[20] ="..-";
temp[21] ="...-";
temp[22] =".--";
temp[23] ="-..-";
temp[24] ="-.--";
temp[25] ="--..";
temp[26] =".......";
temp[27] ="x";
return temp;
}
vector<char> Code::alphacode()
{// This returns a vector containing the alphabet a-z and " "
vector<char> temp;
for (char c='A'; c<='Z'; c++)
temp.push_back(c);
temp.push_back(' ');
temp.push_back('.');
return temp;
}
char Code::decode(string c)
{
for (int i = 0; i < alpha.size(); i++) {
if(c == codewords[i]) {
return alpha[i];
}
}
}
string Code::encode(char c)
{
for (int i=0;i<codewords.size();i++)
{
if (c==alpha[i])
{
return codewords[i];
}
}
}
int main()
{
vector<char> message;
string temp;
getline(cin, temp);
for (int i=0; i <temp.length(); i++)
{
message.push_back(temp[i]);
}
Code C;
cout << C.encode(message) << endl;
}
Your alphacodes and morsecodes are only for Capital letters, so this function returns null resulting in problems.
string Code::encode(char c)
{
for (int i=0;i<codewords.size();i++)
{
if (c==alpha[i])
{
return codewords[i];
}
}
}
Your check for c==alpha[i] should either check ignoring the case or your alpha codes should have small alphabet codes as well. Your morsecodes should have the codes for small alphabets as well and your checks where you map A-Z to 0-28 should accommodate small letters.
Remember, small letters have different ASCII codes than Capital letters.
The following function does not have a return statement at the end.
string Code::encode(char c)
{
for (int i=0;i<codewords.size();i++)
{
if (c==alpha[i])
{
return codewords[i];
}
}
// What should happen if execution gets to this line?
}
If, per chance, your code reaches the end of the function, you will run into undefined behavior. That could be the source of your problem.