About the solution for "reverse-string" in leetcode - c++

https://leetcode.com/problems/reverse-string/
Here is my solution:
class Solution {
public:
string reverseString(string s) {
// if(s.size() == 0 || s.size() == 1)
// return s;
string::size_type i = 0;
string::size_type j = s.size() - 1;
while (i < j)
{
char temp = s[i];
s[i] = s[j];
s[j] = temp;
i++;
j--;
}
return s;
}
};
But this solution is not passed.
When i uncomment these two lines: if(s.size() == 0 || s.size() == 1) return s;, the code pass. i am confused, i think these code are equal.

When the length is 0 you get out of bounds access (j becomes a large number as it is unsigned).
The length 1 case should be safe to keep commented.

Related

previous greatest palindrome numbers before a given palindrome number

The Question is:
You are given a number 'N' in the form of a string 'S', which is a palindrome. You need to find the greatest number strictly less than 'N' which is also a palindrome.
I tried to solve this question but is giving wrong answer for some test cases. can anyone help me to correct my code.
Below is my code:
string nextSmallerPalindrome(string &s)
{
int n = s.length();
string ans = "";
if(n == 1)
{
s[0]--;
return s;
}
if(s == "11")
{
return "9";
}
// For Handling odd cases
if(n % 2 != 0)
{
int idx = n / 2;
int diff = 0;
if(s[idx] == '0')
{
s[idx] = '9';
diff = 1;
}
else
{
s[idx]--;
}
idx--;
while(idx >= 0 && diff == 1)
{
if(s[idx] == '0')
{
s[idx] = '9';
idx--;
}
else
{
s[idx]--;
diff = 0;
break;
}
}
int i = 0;
while(i < n && s[i] == '0')
{
i++;
}
for(; i < n; i++)
{
ans = ans + s[i];
}
int new_n = ans.length();
int j = 0;
int k = new_n - 1;
while(j < k)
{
if(ans[j] == ans[k])
{
j++;
k--;
}
else
{
ans[k] = ans[j];
j++;
k--;
}
}
return ans;
}
else // For handling even cases
{
int idx = n / 2 - 1;
int diff = 0;
if(s[idx] == '0')
{
s[idx] = '9';
diff = 1;
}
else
{
s[idx]--;
}
idx--;
while(idx >= 0 && diff == 1)
{
if(s[idx] == '0')
{
s[idx] = '9';
idx--;
}
else
{
s[idx]--;
diff = 0;
break;
}
}
int i = 0;
while(i < n && s[i] == '0') // For ignoring Zeros from front of the string
{
i++;
}
for(; i < n; i++) //storing all the string s in new string ans after ignoring front 0
{
ans = ans + s[i];
}
int new_n = ans.length();
int j = 0;
int k = new_n - 1;
while(j < k) // checking and changing the last half into first half
{
if(ans[j] == ans[k])
{
j++;
k--;
}
else
{
ans[k] = ans[j];
j++;
k--;
}
}
return ans;
}
}
Input Format:
The first line of the input contains an integer T denoting the number of test cases.
The first and the only line of each test case contains a string 'S', denoting the number whose next smaller palindrome is to be found.
Test Case:
19
7
77
101
1001
1221
144441
3444444443
57855875
10000001
11
1
111
101
1001
11011
1110111
1190911
20002
10011001
Excuse me, but I will not fix the code. I will rather describe how I would solve it. If you like the idea, then you will have a very easy time doing it.
A palindrome has n digits. n may be pair or odd. The first n / 2 digits (rounded upwards) is a number. Get that number (cut down the digits in the second half) and subtract 1.
Look at the result and the number of its digits. If subtracting 1 decreases the number of digits of your half-number, then handle that accordingly. Should be easy if you have the right idea.
Seems like using the same expression for idx in even cases as odd cases works better.
(It still doesn't handle the case for 7, though.)
Change this:
else // For handling even cases
{
int idx = n / 2 - 1;
to this:
else // For handling even cases
{
int idx = n / 2;
Results:
here's a working code
#include <bits/stdc++.h>
string nextSmallerPalindrome(string &s) {
// Write your code here.
string ans = s ;
if(s=="11"){
return "9";
}
int c = 0 ;
if(s.size()%2==1){
int k = s.size()/2 ;
//string ans = s ;
while(k>=0){
if(k==0 && ans[k]=='1' && ans.size()>1){
// cout<<"hola\n";
ans = ans.substr(1,ans.size()-2);
ans=ans+'9';
break;
}
if(ans[k]-'0'!=0){
int temp = ans[k]-'0';
temp-= 1 ;
ans[k] = (temp) +'0';
ans[s.size()-1-k] = (temp) +'0';
return ans;
}
else{
ans[k] = (9) +'0';
ans[s.size()-1-k] = (9) +'0';
k--;
}
}
}
else{
int k = s.size()/2 ;
while(k>=0){
if(k==0 && ans[k]=='1' && ans.size()>1){
ans = ans.substr(1,ans.size()-2);
ans=ans+'9';
break;
}
if(ans[k]-'0'!=0){
int temp = ans[k]-'0';
temp-= 1 ;
ans[k] = (temp) +'0';
ans[s.size()-1-k] = (temp) +'0';
return ans ;
}
else{
ans[k] = (9) +'0';
ans[s.size()-1-k] = (9) +'0';
if(c==0){
c++;
k-=2;
}
else k--;
}
}
}
return ans ;
}

If the only input is a String and an additional String is created, is the function O(n) space complexity?

For example:
string longestPalStartingAtIndex(string s, int index) {
int i = index - 1;
int j = index + 1;
while (j < s.size() && s.at(index) == s.at(j)) j++;
while (i >= 0 && j < s.size()) {
if (s.at(i) == s.at(j)) {
i--; j++;
}
else {break;}
}
return s.substr(i + 1, (j - 1) - (i + 1) + 1);
}
string longestPalindrome(string s) {
string longest; string temp;
for (int i = 0; i < s.size(); i++) {
temp = longestPalStartingAtIndex(s, i);
if (longest.size() < temp.size()) longest = temp;
}
return longest;
}
In longestPalindrome, since n is the string s or the length of it, is creating an additional string (meant to store some substring of s) going to make the function O(n) space complexity?
Yes. You're correct. The code you've shown has O(s.size()) space complexity.
Arguably the function calls to longestPalStartingAtIndex will also copy s and require space, but in the end we're talking about O(some_constant * s.size()) so it is still O(s.size()).

what is wrong in my logic reversing vowels in a string?

I tried solving a problem in leetcode
which asks the programmer to reverse the vowels in the given string.
When I wrote my code in C, it ran fine and passed all the test cases.
I tried writing the same code in C++ but for a particular test case, it failed.
bool isVowel(char a)
{
if(a == 'a' || a == 'e' || a == 'i' || a == 'o' || a == 'u')
return true;
if(a == 'A' || a == 'E' || a == 'I' || a == 'O' || a == 'U')
return true;
return false;
}
class Solution {
public:
string reverseVowels(string s) {
int i, j, k;
int len = s.length();
j = s.length() - 1;
i = 0;
k = 0;
string result;
//char result[len];
if (j < 0)
return s;
while(j >= 0) {
if (isVowel(s[j])) {
result[k] = s[j];
k++;
}
j--;
}
k = 0;
j = s.length() - 1;
while (i <= j) {
if(isVowel(s[i])) {
s[i] = result[k];
k++;
}
i++;
}
return s;
}
};
For some reason, when the input is "A new order began, a more Roman age bred Rowena." there is an error message AddressSanitizer: stack-buffer-overflow on address 0x7ffd4a543ab0 at pc 0x000000405efb.
When I tried to debug, I found that, the first while loop gets infinite. But when I replace the string result to char result[len], my code is working fine.
What is wrong in my approach?
Thanks
hago
You may not use the subscript operator for an empty string to change its value.
So your program has undefined behavior.
Pay attention to that in any case you are not reversing vowels in a string. You are trying to create a new string with reversed vowels from a given string. But this is not the same thing.
I can suggest the following Solution.:)
#include <iostream>
#include <string>
#include <cstring>
#include <cctype>
class Solution final
{
private:
static bool isVowel( char c )
{
const char *vowels = "AEIOU";
return std::strchr( vowels, std::toupper( static_cast<unsigned char>( c ) ) );
}
public:
static std::string & reverseVowels( std::string &s )
{
auto first = std::begin( s ), last = std::end( s );
do
{
while ( first != last && !isVowel( *first ) ) ++first;
if ( first != last )
{
while ( --last != first && !isVowel( *last ) );
}
if ( first != last ) std::iter_swap( first++, last );
} while ( first != last );
return s;
}
};
int main()
{
std::string s( "I am trying to write a program in C++" );
std::cout << s << '\n';
std::cout << Solution::reverseVowels( s ) << '\n';
return 0;
}
The program output is
I am trying to write a program in C++
i am tryong ta wreti o prigram In C++
Pay into account that the letter 'y' is not included in the set of vowels.
Your solution is correct but with a simple mistake.
When you declare string result; then this variable is declared with 0 size. So whenever you try to place character at some position (i.e result[0], result[1], ...) it finds that there is no allocated memory for this variable. So it throws error.
In stead of placing character to the result, you can add the character to this string.
So you can write result = result + s[j];
Code snap should be like this -
string result = "";
//char result[len];
if (j < 0)
return s;
while(j >= 0) {
if (isVowel(s[j])) {
result = result + s[j];
}
j--;
}
But adding character to a string takes more run-time.
Besides this, you can also use string.push_back() to add a single character to a string. It's complexity is overall O(n), n = length of the final string.
string result = "";
//char result[len];
if (j < 0)
return s;
while(j >= 0) {
if (isVowel(s[j])) {
result.push_back(s[j]);
}
j--;
}

Leetcode 28 - Implement strStr(): question

I am experiencing a bug in my submissions for Leetcode 28 that has thus far eluded me. My code works for most test cases but I am getting hung up on scenarios such as haystack = "mississippi", needle = "issip".
I have tried debugging and found that the entire haystack string is iterated through and it is returning -1 or not found. The substring length it is finding at each occurrence of 'i' is 4, 1, 1.
int strStr(string haystack, string needle) {
if (needle.empty()) {
return 0;
}
if (haystack.empty() && !needle.empty()) {
return -1;
}
int i = 0, j = 0, ans = 0;
for (i; i < haystack.length(); i++) {
if (haystack[i] == needle[0]) {
j = 0;
ans = i;
for (j; j < needle.length(); j++) {
/*
if (haystack[i++] == needle[j]) {
continue;
}
else {
break;
}
*/
if (haystack[i++] != needle[j]) {
break;
}
}
if (j == needle.length()) {
return ans;
}
}
if (j == needle.length()) {
return ans;
}
}
return -1;
}
Input: "mississippi", "issip"
Output: -1 (ans = 10, j = 1)
The function has several drawbacks.
For starters it should be declared like
std::string::size_type strStr( const std::string &haystack, const std::string &needle );
and if the second string is not found in the first string the function should return std::string::npos as all similar member functions of the class std::string do.
The function parameters shell be of constant referenced types.
The condition in this if-statement
if (haystack.empty() && !needle.empty())
has a redundant operand. It could be rewritten like
if (haystack.empty())
This loop
for (i; i < haystack.length(); i++)
should stop its iterations when the size of the tail of the first string is less than the size of the second string.
in this if-statement
if (haystack[i++] != needle[j]) {
the variable i is incremented that results in incrementing the variable two times: one in this statement and the second time in the loop.
The second pair of these statements
if (j == needle.length()) {
return ans;
is redundant.
The function can be written the following way as it is shown in the demonstrative program.
#include <iostream>
#include <string>
std::string::size_type strStr( const std::string &haystack, const std::string &needle )
{
if ( needle.empty() )
{
return 0;
}
else if ( haystack.empty() )
{
return -std::string::npos;
}
else
{
std::string::size_type ans = std::string::npos;
auto n1 = haystack.length();
auto n2 = needle.length();
for ( std::string::size_type i = 0; ans == std::string::npos && i + n2 <= n1; i++ )
{
std::string::size_type j = 0;
while ( j < n2 && haystack[i+j] == needle[j] ) j++;
if ( j == n2 ) ans = i;
}
return ans;
}
}
int main()
{
std::string haystack( "mississippi" );
std::string needle( "issip" );
std::cout << strStr( haystack, needle ) << '\n';
return 0;
}
Its output is
4
The problem is that you modify i in
if (haystack[i++] != needle[j]) {
Thus preventing a second potential match from being explored. Try
if (haystack[i + j] != needle[j]) {
and fix any knock-on issues. I expect it to work as-is, though.

Reverse an array without affecting special characters

Is it possible to reverse an array without affecting the special characters ? By special characters, I mean anything characters not included from 'a' to 'z' and 'A' to 'Z'. I am short of ideas to build the algorithm, I still haven't it figured out.
One simple solution would be to Simple Solution:
1) Create a temporary character array --> ex: myArr[].
2) Copy alphabetic characters from the given array to myArr[].
3) Reverse myArr[] using standard string reversal algorithm.
4) Now traverse input string and myArr in a single loop. Wherever there is alphabetic character is input string, replace it with current character of myArr[].
Little problem with above solution, it requires extra space and it does two traversals of input string.
You can reverse with one traversal and without extra space. Below is algorithm.
1) Let input string be 'str[]' and length of string be 'a'
2) l = 0, r = a-1
3) While l is smaller than r, do following
a) If str[l] is not an alphabetic character, do l++
b) Else If str[r] is not an alphabetic character, do r--
c) Else swap str[l] and str[r]
Here's a solution that will do it "in place" in one pass.
bool isspecial(char c)
{
if ((c >= 'a') && (c <= 'z')) return false;
if ((c >= 'A') && (c <= 'Z')) return false;
return true;
}
void rev(char* array, int N)
{
int i = 0; // i points to the first index of the array
int j = N - 1; // j points to the last index of the array
while (i < j)
{
if (isspecial(array[i]))
{
i++;
}
else if (isspecial(array[j]))
{
j--;
}
else
{
char tmp = array[i];
array[i] = array[j];
array[j] = tmp;
i++;
j--;
}
}
}
Console.WriteLine("enter any string");
string str = Console.ReadLine();
string[] revstr = new string[str.Length];
for (int i = 0; i < str.Length; i++)
{
int ch = Convert.ToInt16(str.ToLower()[i]);
if ((ch < 97 || ch > 122))
{
revstr[i] = str[i].ToString();
}
}
for (int k = str.Length - 1; k >= 0; k--)
{
int ch = Convert.ToInt16(str.ToLower()[k]);
if (!(ch < 97 || ch > 122))
{
for (int j = 0; j < str.Length; j++)
{
if (revstr[j] == null)
{
revstr[j] = str[k].ToString();
break;
}
}
}
}
for (int s = 0; s < revstr.Length; s++)
{
Console.Write(revstr[s]);
}
If you want the position of the special characters to remain the same and the rest of the string to be reversed then this should work -
#include <iostream>
using namespace std;
void swap(char& a, char& b)
{
char temp = a;
a = b;
b = temp;
}
int main()
{
string s = "Hell$o World";
for(int i = 0, j = s.length() -1;i < s.length()/2; i++, j--) {
while((s[i] <= 'a' && s[i] >= 'Z') || s[i] >= 'z' || s[i] <= 'A') {
i++;
}
while((s[j] <= 'a' && s[j] >= 'Z') || s[j] >= 'z' || s[j] <= 'A') {
j--;
}
swap(s[i], s[j]);
}
cout << s << endl; //dlro$W olleH
return 0;
}