I am writing code for Leetcode problem 38. Count and Say. It doesn't pass the cases, so I add some cout to debug. Please tell me is there a normal way to debug nested for loop, where should I add the cout expression. I don't want to know how to modify the code to pass the cases.
Here is my code:
class Solution {
public:
string countAndSay(int n) {
string cur("1");
while (--n) {
string tmp = cur;
string next;
for (int i = 0; i < tmp.size();) {
cout << "i:" << i << endl;
int count = 1;
for (int j = i + 1; j < tmp.size(); j++) {
if (tmp[j] != tmp[0]) {
break;
}
count++;
}
cout << "count:" << count << endl;
next += std::to_string(count) + tmp[0];
cout << "cur:" << cur << endl;
i += count;
}
cur = next;
cout << n << cur << endl;
}
return cur;
}
};
You're gonna have to use a debugger for that, and step by step go through your algorithm to find the bugs. It's hard to debug someone else's algorithm.
This'll pass through:
#include <string>
struct Solution {
static const std::string countAndSay(int n) {
if (not n) {
return "";
}
std::string res = "1";
while (--n) {
std::string curr = "";
for (int index = 0; index < res.size(); index++) {
int count = 1;
while ((index + 1 < res.size()) and (res[index] == res[index + 1])) {
count++;
index++;
}
curr += std::to_string(count) + res[index];
}
res = curr;
}
return res;
}
};
Java Solutions
class Solution {
public String countAndSay(int n) {
if (n == 1)
return "1";
String prev = countAndSay(n - 1);
StringBuilder str = new StringBuilder();
int i = 0;
while (i < prev.length()) {
char curr = prev.charAt(i);
int j = 0;
while (i + j < prev.length() && prev.charAt(i + j) == curr)
j++;
str.append(j);
str.append(curr);
i += j;
}
return str.toString();
}
}
Here is one of LeetCode's solutions using regex:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Solution {
public String countAndSay(int n) {
String currSeq = "1";
// Pattern to match the repetitive digits
String regexPattern = "(.)\\1*";
Pattern pattern = Pattern.compile(regexPattern);
for (int i = 1; i < n; ++i) {
Matcher m = pattern.matcher(currSeq);
StringBuffer nextSeq = new StringBuffer();
// each group contains identical and adjacent digits
while (m.find()) {
nextSeq.append(m.group().length() + String.valueOf(m.group().charAt(0)));
}
// prepare for the next iteration
currSeq = nextSeq.toString();
}
return currSeq;
}
}
and here's another LeetCode's solution also using Sliding Window:
class Solution {
public String countAndSay(int n) {
LinkedList<Integer> prevSeq = new LinkedList<Integer>();
prevSeq.add(1);
// Using -1 as the delimiter
prevSeq.add(-1);
List<Integer> finalSeq = this.nextSequence(n, prevSeq);
StringBuffer seqStr = new StringBuffer();
for (Integer digit : finalSeq) {
seqStr.append(String.valueOf(digit));
}
return seqStr.toString();
}
protected LinkedList<Integer> nextSequence(int n, LinkedList<Integer> prevSeq) {
if (n <= 1) {
// remove the delimiter before return
prevSeq.pollLast();
return prevSeq;
}
LinkedList<Integer> nextSeq = new LinkedList<Integer>();
Integer prevDigit = null;
Integer digitCnt = 0;
for (Integer digit : prevSeq) {
if (prevDigit == null) {
prevDigit = digit;
digitCnt += 1;
} else if (digit == prevDigit) {
// in the middle of the sub-sequence
digitCnt += 1;
} else {
// end of a sub-sequence
nextSeq.add(digitCnt);
nextSeq.add(prevDigit);
// reset for the next sub-sequence
prevDigit = digit;
digitCnt = 1;
}
}
// add the delimiter for the next recursion
nextSeq.add(-1);
return this.nextSequence(n - 1, nextSeq);
}
}
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions with a variety of languages and explanations, efficient algorithms, as well as asymptotic time/space complexity analysis1, 2 in there.
Related
I'm trying to print the last level in a min heap. I thought I had code that works, but one of the test cases fail. In terms of the test cases, I only have access to how the output does not match.
Here is my code:
#include "MinHeap.h"
#include <math.h>
using std::log2;
vector<int> lastLevel(MinHeap & heap)
{
// Your code here
vector<int> leaves;
int capacity = pow(2, log2(heap.elements.size()) + 1) - 1;
for (unsigned leaf = capacity / 2; leaf < heap.elements.size(); leaf++) {
leaves.push_back(heap.elements[leaf]);
}
return leaves;
}
And here is the MinHeap class that goes along with it:
#include "MinHeap.h"
MinHeap::MinHeap(const vector<int> & vector)
{
int inf = numeric_limits<int>::min();
elements.push_back(inf);
elements.insert(elements.end(), vector.begin(), vector.end());
buildHeap();
}
MinHeap::MinHeap()
{
int inf = numeric_limits<int>::min();
elements.push_back(inf);
}
void MinHeap::buildHeap()
{
std::sort(elements.begin() + 1, elements.end());
}
void MinHeap::heapifyDown(int index)
{
int length = elements.size();
int leftChildIndex = 2 * index;
int rightChildIndex = 2 * index + 1;
if (leftChildIndex >= length)
return; // index is a leaf
int minIndex = index;
if (elements[index] > elements[leftChildIndex]) {
minIndex = leftChildIndex;
}
if ((rightChildIndex < length)
&& (elements[minIndex] > elements[rightChildIndex])) {
minIndex = rightChildIndex;
}
if (minIndex != index) {
// need to swap
int temp = elements[index];
elements[index] = elements[minIndex];
elements[minIndex] = temp;
heapifyDown(minIndex);
}
}
void MinHeap::heapifyUp(int index)
{
if (index < 2)
return;
int parentIndex = index / 2;
if (elements[parentIndex] > elements[index]) {
int temp = elements[parentIndex];
elements[parentIndex] = elements[index];
elements[index] = temp;
heapifyUp(parentIndex);
}
}
void MinHeap::insert(int newValue)
{
int length = elements.size();
elements.push_back(newValue);
heapifyUp(length);
}
int MinHeap::peek() const
{
return elements.at(1);
}
int MinHeap::pop()
{
int length = elements.size();
int p = -1;
if (length > 1) {
p = elements[1];
elements[1] = elements[length - 1];
elements.pop_back();
heapifyDown(1);
}
return p;
}
void MinHeap::print() const
{
if (elements.size() > 1) {
int length = elements.size();
cout << "[";
for (int i = 1; i < length - 1; i++) {
cout << elements[i] << ", ";
}
cout << elements[elements.size() - 1] << "]" << endl;
} else {
cout << "[ ]" << endl;
}
}
Here is the output I get showing one of the test cases fail:
tests.cpp:31: FAILED:
REQUIRE( s_lastLevel(h) == lastLevel(h) )
with expansion:
{ 1804289383 (0x6b8b4567), 1681692777 (0x643c9869) }
==
{ 1681692777 (0x643c9869) }
===============================================================================
test cases: 1 | 1 failed
assertions: 3 | 2 passed | 1 failed
I'm not sure why my initial approach is failing. Much help is appreciated.
It seems like the problem is in this line:
int capacity = pow(2, log2(heap.elements.size()) + 1) - 1;
What you are doing here is equivalent to:
int capacity = 2 * heap.elements.size() - 1;
What you instead want to do is get the index of the parent of the last element and increment by one as the starting position of your iteration. Since children of a node at i are at 2i and 2i+1, you can simply divide the index of the last node (n-1) by two and add one. You can check that this must be a leaf since its children would be at 2 * ((n-1)/2 + 1) and 2 * ((n-1)/2 + 1) + 1 which are both guaranteed equal or grater than n. So this will return all leaves:
int start = (heap.elements.size() - 1) / 2 + 1;
for (unsigned leaf = start; leaf < heap.elements.size(); leaf++) {
leaves.push_back(heap.elements[leaf]);
}
return leaves;
If it is just the last level you want, start at the largest power of two smaller than the index of the last element (n-1):
int start = 1 << (int)(log2(heap.elements.size()-1));
for (unsigned leaf = start; leaf < heap.elements.size(); leaf++) {
leaves.push_back(heap.elements[leaf]);
}
return leaves;
There is this problem on Leetcode , Link of the problem is : https://leetcode.com/problems/largest-time-for-given-digits/
I have written the code for this problem , and according to me my code is correct but still my code is not passing all the test cases and I am stuck debugging where is the issue in my Code .
Can Anybody please help me with this ?
class Solution {
public:
bool isValid(string s){
if(s[0] > '2') return false;
if(s[0] == '2'){
if(s[1] >= '4'){
return false ;
}
}
if(s[2] >=6) return false ;
return true ;
}
vector<vector<int>> permute(vector<int> &nums)
{
vector<vector<int>> result;
//Base Case For The Problem:
if (nums.size() <= 1)
return {nums};
for (int i = 0; i < nums.size(); i++)
{
vector<int> v(nums.begin(), nums.end());
v.erase(v.begin() + i);
auto res = permute(v);
for (int j = 0; j < res.size(); j++)
{
vector<int> _v = res[j];
_v.insert(_v.begin(), nums[i]);
result.push_back(_v);
}
}
return result;
}
string largestTimeFromDigits(vector<int>& A) {
vector<vector<int>> res ;
vector<string> valid ; //For Only Storing the Valid Time Permutations
res = permute(A);
//Now , Iterating Over All the Permutations:
for(int i=0 ; i<res.size() ; i++){
string curr = "";
for(int j=0 ; j<res[i].size() ; ++j){
curr += res[i][j];
}
if(isValid(curr)) valid.push_back(curr);
}
sort(valid.begin() , valid.end());
string ans = ""; //The Final Answer that we have to return at the end.
if(valid.size() > 0){
//Now , perform the Required Operations:
string temp = valid[valid.size() - 1];
ans = temp.substr(0,2) + ":" + temp.substr(2);
}
return ans;
}
};
Two problems in your code, both related to mixing int with char. The first is here:
if(s[2] >=6 ) {
return false ;
}
Because of this condition your isValid returns false always. No character in the range '0'...'9' is smaller than the integer 6. Compare the char to a char:
if(s[2] >='6' ) {
return false ;
}
Next, here
curr += res[i][j];
res[i][j] is an integer, but you want to add a character to the string:
curr += static_cast<char>(res[i][j]) + '0';
After fixing those two I get expected output at least for input {2,2,2,2}, see here: https://godbolt.org/z/35r3f9.
I have to mention that you would have found those problems yourself if you had used a debugger. Getting better in coding is not that much about making less mistakes, but about getting better at finding and fixing them. The debugger is an essential tool to do that.
C++
You can use std::prev_permutation and sort first:
// The following block might slightly improve the execution time;
// Can be removed;
static const auto __optimize__ = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
// Most of headers are already included;
// Can be removed;
#include <cstdint>
#include <string>
#include <vector>
#include <algorithm>
static const struct Solution {
static const std::string largestTimeFromDigits(std::vector<int>& A) {
std::sort(std::begin(A), std::end(A), std::greater<int>());
do if (
(A[0] < 2 || A[0] == 2 && A[1] < 4) &&
A[2] < 6
) {
return std::to_string(A[0]) + std::to_string(A[1]) + ":" + std::to_string(A[2]) + std::to_string(A[3]);
}
while (std::prev_permutation(std::begin(A), std::end(A)));
return "";
}
};
Here is LeetCode's official solution in C++:
class Solution {
public:
string largestTimeFromDigits(vector<int>& A) {
int max_time = -1;
// prepare for the generation of permutations next.
std::sort(A.begin(), A.end());
do {
int hour = A[0] * 10 + A[1];
int minute = A[2] * 10 + A[3];
if (hour < 24 && minute < 60) {
int new_time = hour * 60 + minute;
max_time = new_time > max_time ? new_time : max_time;
}
} while(next_permutation(A.begin(), A.end()));
if (max_time == -1) {
return "";
} else {
std::ostringstream strstream;
strstream << std::setw(2) << std::setfill('0') << max_time / 60
<< ":" << std::setw(2) << std::setfill('0') << max_time % 60;
return strstream.str();
}
}
};
Alternative solution with regular expression:
This'd be difficult in C++ though:
class Solution:
def largestTimeFromDigits(self, A: List[int]) -> str:
for i in range(2359, -1, -1):
if i < 1000:
i = format(i, '04')
if int(re.findall(r'\d{2}$', str(i))[0]) > 59:
continue
l = list(map(int, str(i)))
for j in A:
if j in l:
l.remove(j)
if len(l) == 0:
hm = re.findall(r'.{2}', str(i))
return f'{hm[0]}:{hm[1]}'
return ""
Alternative solution using three loops in Java:
public final class Solution {
public static final String largestTimeFromDigits(
final int[] A
) {
String res = "";
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
for (int k = 0; k < 4; ++k) {
if (i == j || i == k || j == k) {
continue;
}
String hour = "" + A[i] + A[j];
String minute = "" + A[k] + A[6 - i - j - k];
String time = hour + ":" + minute;
if (
hour.compareTo("24") < 0 &&
minute.compareTo("60") < 0 &&
res.compareTo(time) < 0
) {
res = time;
}
}
}
}
return res;
}
}
References
For additional details, please see the Discussion Board where you can find plenty of well-explained accepted solutions with a variety of languages including low-complexity algorithms and asymptotic runtime/memory analysis1, 2.
Q: Make palindromic string non-palindromic by rearranging its letters.
I just want to know why my solution is failing (wrong answer) for some test cases when i submit the code. I am sure there is an easy solution such as sorting the whole string?
void makeNonPalindrome(string& s)
{
bool ans = false;
int l = s.length();
if(l % 2 == 0)
{
for(int i = l/2; i < l; i++)
{
if(s[l/2 - 1] != s[i])
{
swap(&s[l/2 - 1],&s[i]);
ans = true;
break;
}
}
if(!ans)
{
for(int i = 0; i < l/2-1; i++)
{
if(s[l/2 - 1] != s[i])
{
ans = true;
break;
}
}
}
}
else
{
for(int i = l/2 + 1; i < l; i++)
{
if(s[l/2 - 1] != s[i])
{
swap(&s[l/2 - 1],&s[i]);
ans = true;
break;
}
}
if(!ans)
{
for(int i = 0; i < l/2-1; i++)
{
if(s[l/2 - 1] != s[i])
{
ans = true;
break;
}
}
}
if(!ans)
{
if(s[l/2] != s[0])
{
swap(&s[l/2],&s[0]);
ans = true;
}
}
}
if(ans)
cout << s << '\n';
else
cout << -1 << '\n';
}
Rearranging a palindrome so it become non-palindromic can be done quite fast, by simply trying to swap two adjacent letters in the string if they are different.
For instance, in 'bob', you'd need to find the first distinct adjacent letters (that is b and o in our case), and swap them. The result would then be 'obb', which is not a palindrome.
void makeNonPalindrome(std::string& s) {
char tmp;
for (unsigned i = 0; i < s.length() - 1; i++) {
if (s[i] != s[i+1]) { // then swap s[i] and s[i+1]
tmp = s[i];
s[i] = s[i+1];
s[i+1] = tmp;
std::cout << s << '\n';
return;
}
}
std::cout << -1 << '\n';
}
This is a simpler way to make a palindrome non palindromic.
NB: this function assumes that the input is indeed a palindrome, so if you feed it a string like 'oob', it will output 'bob' which is a palindrome.
Given the input palindrome string s you can just use find_first_not_of to determine if the string can be rearranged into a non-palindrome at all, and if so what characters should be swapped to do this. For example:
const auto foo = s.find_first_not_of(s[0], 1);
If foo == string::npos it means that there isn't a possible non-palindrome rearrangement. Otherwise swap(s[0], s[foo]) will break the palindrome.
Live Example
For the following structure of a trie.
struct Trie {
bool eow; //when a Trie field isWord = true, hence there is a word
char letter;
Trie *letters[27];
};
I'm trying to create a function for an auto completion program, that basically prints out words in a trie given a specific string prefix
Here is what i have:
int wordcheck( TrieNode &node )
{
if (node.isWord == 1) // you have found your word, so return true
{
return 1;
}
for (int i = 0; i < 26; i++)
{
if (node.letters[i] != NULL && wordcheck(*(node.letters[i])))
{
return 1;
}
}
return 0;
}
string find (TrieNode &node, const string &word, string acc)
{
if (word.length() == 0)
{
string x = "";
if (node.isWord == 1){
x = " ";
int check = 1;
for(int i = 0; i < 26; i++)
{
if (node.letters[i] != NULL && wordcheck(*(node.letters[i])))
{
x = x + acc; check = 0; break;
}
}
if(check == 1)
{ return x; }
}
for (int i = 0; i < 26; i++){
if (node.letters[i] != NULL && wordcheck(*(node.letters[i])))
{
char let = (char)(i + (int)'a');
if (x[x.length() - 1 ] == ' ')
{
x = x + acc;
}
x = x + node.letters[i]->letter
+ find(*(node.letters[i]), word, acc + node.letters[i]->letter);
}
}
return x;
}
else if (node.letters[word[0] - 'a'] == NULL)
{ return ""; }
else {
return word[0] + find(*(node.letters[ word[0] - 'a']),
word.substr(1, word.length()-1),
acc + word[0]);
}
}
it seems to work other than the fact it if i give it a long prefix it will print words shorter than the prefix. I used accumulative recursion, and im sure there is a more efficient way of doing this. My question is if anyone could make it so that i return the right strings, or guide me through a easier algorithm if possible?
I'm trying to create a function for an auto completion program, that basically prints out words in a trie given a specific string prefix
I am not going to analyse your program - for me it is too complicated, e.g. I don't get any idea what wordcheck is supposed to do? Why is it not bool but int? Do you really need to check that your sub-trie has any word, do you really have non empty Trie without words in it?
For first - to print all words which begin with the given prefix - you need to go to the node where all these words begin:
TrieNode* TreeNode::get(std::string word)
{
TreeNode* retVal = this;
for (size_t i = 0; i < word.length(); ++i) {
if (Words[i] < 'a' || words[i] > 'z')
throw std::runtime_error("Wrong word");
if (retVal->letters[word[i] - 'a'] != NULL)
retVal = retVal->letters[word[i] - 'a'];
else
return nullptr;
}
return retVal;
}
You need the function which prints all the words from the given node:
void TreeNode::printAll(std::ostream& os, std::string prefix)
{
if (isWord)
os << prefix << "\n";
for (size_t i = 0; i < 26; ++i) {
if (retVal->letters[i] != NULL)
// this recursive call can be replaced with iterative solution with stack
letters[i]->print(os, prefix + char('a' + i));
}
}
And combining these functions - gives you what you want:
void TreeNode::printBeginWith(std::ostream& os, std::string prefix)
{
TreeNode* node = get(prefix);
if (node)
node->printAll(os, prefix);
}
I'm trying to solve a problem that asks to find the largest palindrome in a string up to 20,000 characters. I've tried to check every sub string whether it's a palindrome, that worked, but obviously was too slow. After a little googling I found this nice algorithm
http://stevekrenzel.com/articles/longest-palnidrome. I've tried to implement it, however I can't get it to work. Also the given string contains illegal characters, so I have to convert it to only legal characters and output the longest palindrome with all characters.
Here's my attempt:
int len = original.length();
int longest = 0;
string answer;
for (int i = 0; i < len-1; i++){
int lower(0), upper(0);
if (len % 2 == 0){
lower = i;
upper = i+1;
} else {
lower = i;
upper = i;
}
while (lower >= 0 && upper <= len){
string s2 = original.substr(lower,upper-lower+1);
string s = convert(s2);
if (s[0] == s[s.length()-1]){
lower -= 1;
upper += 1;
} else {
if (s.length() > longest){
longest = s.length();
answer = s2;
}
break;
}
}
}
I can't get it to work, I've tried using this exact algorithm on paper and it worked, please help. Here's full code if you need it : http://pastebin.com/sSskr3GY
EDIT:
int longest = 0;
string answer;
string converted = convert(original);
int len = converted.length();
if (len % 2 == 0){
for (int i = 0; i < len - 1; i++){
int lower(i),upper(i+1);
while (lower >= 0 && upper <= len && converted[lower] == converted[upper]){
lower -= 1;
upper += 1;
}
string s = converted.substr(lower+1,upper-lower-1);
if (s.length() > longest){
longest = s.length();
answer = s;
}
}
} else {
for (int i = 0; i < len; i++){
int lower(i), upper(i);
while (lower >= 0 && upper <= len && converted[lower] == converted[upper]){
lower -= 1;
upper += 1;
}
string s = converted.substr(lower+1,upper-lower-1);
if (s.length() > longest){
longest = s.length();
answer = s;
}
}
}
Okay so I fixed the problems, it works perfectly fine but only if the length of converted string is odd. Please help.
I can see two major errors:
Whether you initialise your upper/lower pointers to i,i or i,i+1 depends on the parity of the palindrome's length you want to find, not the original string. So (without any further optimisations) you'll need two separate loops with i going from 0 to len (len-1), one for odd palindrome lengths and another one for even.
The algorithms should be executed on the converted string only. You have to convert the original string first for it to work.
Consider this string: abc^ba (where ^ is an illegal character), the longest palindrome excluding illegal characters is clearly abcba, but when you get to i==2, and move your lower/upper bounds out by one, they will define the bc^ substring, after conversion it becomes bc, and b != c so you concede this palindrome can't be extended.
#include <iostream>
using namespace std;
int main()
{
string s;
cin >> s;
signed int i=1;
signed int k=0;
int ml=0;
int mi=0;
bool f=0;
while(i<s.length())
{
if(s[i]!=s[i+1])
{
for(k=1;;k++)
{
if(!(s[i-k]==s[i+k] && (i-k)>=0 && (i+k)<s.length()))
{
break;
}
else if(ml < k)
{
ml=k;
mi=i;
f=1;
}
}
}
i++;
}
i=0;
while(i<s.length())
{
if(s[i]==s[i+1])
{
for(k=1;;k++)
{
if(!(s[i-k]==s[k+1+i] && (i-k)>=0 && (k+i)<s.length()))
{
break;
}
else if(ml < k)
{
ml=k;
mi=i;
}
}
}
i++;
}
if(ml < 1)
{
cout << "No Planidrom found";
return 0;
}
if(f==0)
{
cout << s.substr(mi-ml,2*ml+2);
}
else
{
cout << s.substr(mi-ml,2*ml+1);
}
return 0;
}
#biziclop : As you said.. i used 2 while loops. one for even and one for old palindrom string. finally i was able to fix it. thanks for your suggestion.
public void LongestPalindrome()
{
string str = "abbagdghhkjkjbbbbabaabbbbbba";
StringBuilder str1=new StringBuilder();
StringBuilder str2= new StringBuilder();
for (int i = 0; i < str.Length; i++)
{
str1.Append((str[i]));
for (int j = i + 1; j < str.Length; j++)
{
str1.Append((str[j]));
if (Checkpalindrome(str1))
{
str2.Append(str1);
str2.Append(" ");
}
}
str1.Clear();
}
var Palstr = str2.ToString().Split(' ');
var Longestpal = Palstr.Where(a => a.Length >= (Palstr.Max(y => y.Length)));
foreach (var s in Longestpal)
{
Console.WriteLine(s);
}
}
public bool Checkpalindrome(StringBuilder str)
{
string str1 = str.ToString();
StringBuilder str2=new StringBuilder();
var revstr = str1.Reverse();
foreach (var c in revstr )
{
str2.Append(c);
}
if (str1.Equals(str2.ToString()))
{
return true;
}
return false;
}