I was working on one of the Hackerrank programs, Bigger is Greater, and it basically deals with finding the next largest lexicocraphic permutation of a string. I've implemented my solution, following an algorithm described here. I then store all the permutations in a vector, loop through it, and search for the next permutation after my original word, since this algorithm builds the permutations in sorted order.
This works for small inputs, however, as the problem scales to large inputs (long words), it becomes un-runnable. I'm wondering if there's a better approach to this, that still uses the recursive algorithm I've implemented (since it makes sense to me).
#include <map>
#include <cmath>
#include <string>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
/**
* [check_args description]
* @param t [description]
* @param w [description]
* @return [description]
*/
bool check_args(int t, int w) {
if(t < 1 || t > 100000) {
return false;
}
if(abs(w) < 0 || abs(w) > 100) {
return false;
}
return true;
}
/**
* [print_array description]
* @param size [description]
* @param arr [description]
*/
void print_array(int size, string *arr) {
for(int i = 0; i < size; i++) {
cout << arr[i] << endl;
}
}
/**
* [print_array description]
* @param size [description]
* @param arr [description]
*/
void print_array(int size, char *arr) {
for(int i = 0; i < size; i++) {
cout << arr[i];
}
cout << endl;
}
/**
* [print_map description]
* @param m [description]
*/
void print_map(map<char, int> m) {
for(map<char,int>::const_iterator it = m.begin(); it != m.end(); ++it) {
cout << it->first << " " << it->second << endl;
}
}
/**
* [permutation_util description]
* @param str [description]
* @param count [description]
* @param result [description]
* @param level [description]
* RECURSIVE
*/
void permutation_util(char *str, int *count, char *result,
int string_length, int result_length,
int level, vector<string> *acc) {
if(result_length == level) {
acc->push_back(result);
return;
}
for(int i = 0; i < string_length; i++) {
if(count[i] != 0) {
// Continue through with recursion
result[level] = str[i]; // Store the char in the current level of recursion
count[i]--; // We used a char, so decrement the count
permutation_util(str, count, result, string_length, result_length, level + 1, acc);
count[i]++;
}
}
}
/**
* [permutation description]
* @param length [description]
* @param word [description]
* @param result [description]
*/
vector<string> * permutation(string word) {
map<char, int> occurences;
// Populate map
for(int i = 0; i < word.length(); i++) {
if(occurences.count(word[i]) == 0) {
occurences[word[i]] = 1;
}
else {
occurences[word[i]]++;
}
}
char *str = new char[occurences.size()];
int *count = new int[occurences.size()];
int index = 0;
/*
* Build string and counts in the following format:
* Original String: A A B C
* New String (str): A B C
* | | |
* New Count (int): 2 1 1
*
* Where chars are mapped to number of occurences
*/
for(map<char,int>::const_iterator it = occurences.begin(); it != occurences.end(); ++it) {
str[index] = it->first;
count[index] = it->second;
index++;
}
char *result = new char[word.length()];
int result_length = word.length();
int string_length = occurences.size();
// Accumulator to store permutations
vector<string> *acc = new vector<string>();
// Recursive call
permutation_util(str, count, result, string_length, result_length, 0, acc);
return acc;
}
void find_lexicographically_bigger(string word, vector<string> * perms) {
/*
* If the only perm was itself, we know there's nothing that
* could be lexicographically bigger
*/
if(perms->size() == 1) {
cout << "no answer" << endl;
return;
}
/*
* Loop through and find the next greatest word after
* the input
*/
for(int i = 0; i < perms->size(); i++) {
if(perms->at(i) == word) {
// Get next largest
cout << perms->at(i + 1) << endl;
return;
}
}
}
int main() {
int test_cases = 0;
cin >> test_cases;
string *words = new string[test_cases];
// For each test case, gather our words
for(int i = 0; i < test_cases; i++) {
string w;
cin >> w;
words[i] = w;
if(!check_args(test_cases, w.length())) {
return 1;
}
}
// For each word, run the algorithm
for(int i = 0; i < test_cases; i++) {
// Find the next largest word
string word = words[i];
if(word.length() == 1) {
cout << "no answer" << endl;
}
else {
find_lexicographically_bigger(word, permutation(word));
}
}
return 0;
}
std::next_permutation()
\$\endgroup\$