Find number of palindromes that are anagrams in C++ - c++

I am taking part in an online programming contest for fun on http://www.hackerrank.com. One of the problems that I am working on is to find number of anagrams of a string that are palindrome as well. I have solve the problem but when I try to upload it it fails on a number of test cases. As the actual test cases are hidden from me I do not know for sure why its failing but I assume it could be a scalability issue. Now I do not want someone to give me a ready made solution because that would not be fair but I am just curious on what people think about my approach.
Here is the problem description from the website:
Now that the king knows how to find out whether a given word has an anagram which is a palindrome or not, he is faced with another challenge. He realizes that there can be more than one anagram which are palindromes for a given word. Can you help him find out how many anagrams are possible for a given word which are palindromes?
The king has many words. For each given word, the king needs to find out the number of anagrams of the string which are palindromes. As the number of anagrams can be large, the king needs number of anagrams % (109+ 7).
Input format :
A single line which will contain the input string
Output format :
A single line containing the number of anagram strings which are palindrome % (109 + 7).
Constraints :
1<=length of string <= 105
Each character of the string is a lowercase alphabet.
Each testcase has atleast 1 anagram which is a palindrome.
Sample Input 01 :
aaabbbb
Sample Output 01 :
3
Explanation :
Three permutation of given string which are palindrome can be given as abbabba , bbaaabb and bababab.
Sample Input 02 :
cdcdcdcdeeeef
Sample Output 02 :
90
As specified in the problem description input strings can be as large as 10^5, hence all palindromes for a large string is not possible since I will run into number saturation issues. Also since I only need to give a modulo (10^9 + 7) based answer, I thought of taking log of numbers with base (10^9 + 7) and after all computations take antilog of fraction part with base (10^9 + 7) of the answer since that will be the modulo anyway.
My algorithm is as follows:
Store freq of each char (only need to look half of the string since
second half should be same as first one by def of palindrome)
If there are more than one char appearing with odd number of time no palindrome possible
Else for each char's freq incrementally calculate number of palindromes (Dynamic Programming)
For the DP following is the subproblem:
previous_count = 1
For each additional character added number of palindromes = previous_count * (number_of_char_already_seen + 1)/(number of char same as current char)
Here is my code:
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <fstream>
using namespace std;
#define MAX_SIZE 100001
void factorial2 (unsigned int num, unsigned int *fact) {
fact[num]++;
return;
}
double mylog(double x) {
double normalizer = 1000000007.0;
return log10(x)/log10(normalizer);
}
int main() {
string in;
cin >> in;
if (in.size() == 1) {
cout << 1 << endl;
return 0;
}
map<char, int> freq;
for(int i=0; i<in.size(); ++i) {
if (freq.find(in.at(i)) == freq.end()) {
freq[in.at(i)] = 1;
} else {
freq[in.at(i)]++;
}
}
map<char, int> ::iterator itr = freq.begin();
unsigned long long int count = 1;
bool first = true;
unsigned long long int normalizer = 1000000007;
unsigned long long int size = 0;
unsigned int fact[MAX_SIZE] = {0};
vector<unsigned int> numerator;
while (itr != freq.end()) {
if (first == true) {
first = false;
} else {
for (size_t i=1; i<=itr->second/2; ++i) {
factorial2(i, fact);
numerator.push_back(size+i);
}
}
size += itr->second/2;
++itr;
}
//This loop is to cancel out common factors in numerator and denominator
for (int i=MAX_SIZE-1; i>1; --i) {
while (fact[i] != 0) {
bool not_div = true;
vector<unsigned int> newNumerator;
for (size_t j=0; j<numerator.size(); ++j) {
if (fact[i] && numerator[j]%i == 0) {
if (numerator[j]/i > 1)
newNumerator.push_back(numerator[j]/i);
fact[i]--; //Do as many cancellations as possible
not_div = false;
} else {
newNumerator.push_back(numerator[j]);
}
}
numerator = newNumerator;
if (not_div) {
break;
}
}
}
double countD = 0.0;
for (size_t i=0; i<numerator.size(); ++i) {
countD += mylog(double(numerator[i]));
}
for (size_t i=2; i <MAX_SIZE; ++i) {
if (fact[i]) {
countD -= mylog((pow(double(i), double(fact[i]))));
fact[i] = 0;
}
}
//Get the fraction part of countD
countD = countD - floor(countD);
countD = pow(double(normalizer), countD);
if (floor(countD + 0.5) > floor(countD)) {
countD = ceil(countD);
} else {
countD = floor(countD);
}
count = countD;
cout << count;
return 0;
}
Now I have spent a lot of time on this problem and I just wonder if there is something wrong in my approach or am I missing something here. Any ideas?

Note that anagrams are reflexive (they look the same read from the back as from the front), so half the occurrences of each character will be on one side and we just need to calculate the number of permutations of these. The other side will be an exact reversal of this side, so it doesn't add to the number of possibilities. The odd occurrence of a character (if one exists) must always be in the middle, so it can be ignored when calculating the number of permutations.
So:
Calculate the frequencies of the characters
Check that there's only 1 odd frequency
Divide the frequency of each character (rounding down - removes any odd occurrence).
Calculate the permutation of these characters using this formula:
(as per Wikipedia - multiset permutation)
Since the above terms can get quite big, we might want to split the formula up into prime factors so we can cancel out terms so we're left with only multiplication, then I believe we can % 109 + 7 after each multiplication, which should fit into a long long (since (109+7)*105 < 9223372036854775807).
Thanks to IVlad for pointing out a more efficient method of avoiding overflow than above:
Notice that p = 109 + 7 is a prime number, so we can use Fermat's little theorem to compute the multiplicative inverses of the mi mod p, and multiply by these and take the mod at each step instead of dividing. mi-1 = mi(10^9 + 5) (mod p). Using exponentiation by squaring, this will be very fast.
I also found this question (which also has some useful duplicates).
Examples:
Input: aaabbbb
Frequency:
a b
3 4
Div 2:
a b
1 2
Solution:
3!/2!1! = 3
Input: cdcdcdcdeeeef
Frequency:
c d e f
4 4 4 1
Div 2:
c d e f
2 2 2 0
Solution:
6!/2!2!2!0! = 90

The basic formula is:
p!/(a!*b!...*z!)
where p is floor of length/2 of the word and a,b,c..,z denotes the floor of half of frequency of occurrences a,b,c..,z in the word receptively.
The only problem now you are left is how to calculate this. For that, check this out.

Related

Can someone please explain this bit manipulation code to me?

I am new to competitive programming. I recently gave the Div 3 contest codeforces. Eventhough I solved the problem C, I really found this code from one of the top programmers really interesting. I have been trying to really understand his code, but it seems like I am too much of a beginner to understand it without someone else explaining it to me.
Here is the code.
void main(){
int S;
cin >> S;
int ans = 1e9;
for (int mask = 0; mask < 1 << 9; mask++) {
int sum = 0;
string num;
for (int i = 0; i < 9; i++)
if (mask >> i & 1) {
sum += i + 1;
num += char('0' + (i + 1));
}
if (sum != S)
continue;
ans = min(ans, stoi(num));
}
cout << ans << '\n';
}
The problem is to find the minimum number whose sum of digits is equal to given number S, such that every digit in the result is unique.
Eq. S = 20,
Ans = 389 (3+8+9 = 20)
Mask is 9-bits long, each bit represents a digit from 1-9. Thus it counts from 0 and stops at 512. Each value in that number corresponds to possible solution. Find every solution that sums to the proper value, and remember the smallest one of them.
For example, if mask is 235, in binary it is
011101011 // bit representation of 235
987654321 // corresponding digit
==> 124678 // number for this example: "digits" with a 1-bit above
// and with lowest digits to the left
There are a few observations:
you want the smallest digits in the most significant places in the result, so a 1 will always come before any larger digit.
there is no need for a zero in the answer; it doesn't affect the sum and only makes the result larger
This loop converts the bits into the corresponding digit, and applies that digit to the sum and to the "num" which is what it'll print for output.
for (int i = 0; i < 9; i++)
if (mask >> i & 1) { // check bit i in the mask
sum += i + 1; // numeric sum
num += char('0' + (i + 1)); // output as a string
}
(mask >> i) ensures the ith bit is now shifted to the first place, and then & 1 removes every bit except the first one. The result is either 0 or 1, and it's the value of the ith bit.
The num could have been accumulated in an int instead of a string (initialized to 0, then for each digit: multiply by 10, then add the digit), which is more efficient, but they didn't.
The way to understand what a snippet of code is doing is to A) understand what it does at a macro-level, which you have done and B) go through each line and understand what it does, then C) work your way backward and forward from what you know, gaining progress a bit at a time. Let me show you what I mean using your example.
Let's start by seeing, broadly (top-down) what the code is doing:
void main(){
// Set up some initial state
int S;
cin >> S;
int ans = 1e9;
// Create a mask, that's neat, we'll look at this later.
for (int mask = 0; mask < 1 << 9; mask++) {
// Loop state
int sum = 0;
string num;
// This loop seems to come up with candidate sums, somehow.
for (int i = 0; i < 9; i++)
if (mask >> i & 1) {
sum += i + 1;
num += char('0' + (i + 1));
}
// Stop if the sum we've found isn't the target
if (sum != S)
continue;
// Keep track of the smallest value we've seen so far
ans = min(ans, stoi(num));
}
// Print out the smallest value
cout << ans << '\n';
}
So, going from what we knew about the function at a macro level, we've found that there are really only two spots that are obscure, the two loops. (If anything outside of those are confusing to you, please clarify.)
So now let's try going bottom-up, line-by-line those loops.
// The number 9 appears often, it's probably meant to represent the digits 1-9
// The syntax 1 << 9 means 1 bitshifted 9 times.
// Each bitshift is a multiplication by 2.
// So this is equal to 1 * (2^9) or 512.
// Mask will be 9 bits long, and each combination of bits will be covered.
for (int mask = 0; mask < 1 << 9; mask++) {
// Here's that number 9 again.
// This time, we're looping from 0 to 8.
for (int i = 0; i < 9; i++) {
// The syntax mask >> i shifts mask down by i bits.
// This is like dividing mask by 2^i.
// The syntax & 1 means get just the lowest bit.
// Together, this returns true if mask's ith bit is 1, false if it's 0.
if (mask >> i & 1) {
// sum is the value of summing the digits together
// So the mask seems to be telling us which digits to use.
sum += i + 1;
// num is the string representation of the number whose sum we're finding.
// '0'+(i+1) is a way to convert numbers 1-9 into characters '1'-'9'.
num += char('0' + (i + 1));
}
}
}
Now we know what the code is doing, but it's hard to figure out. Now we have to meet in the middle - combine our overall understanding of what the code does with the low-level understanding of the specific lines of code.
We know that this code gives up after 9 digits. Why? Because there are only 9 unique non-zero values (1,2,3,4,5,6,7,8,9). The problem said they have to be unique.
Where's zero? Zero doesn't contribute. A number like 209 will always be smaller than its counterpart without the zero, 92 or 29. So we just don't even look at zero.
We also know that this code doesn't care about order. If digit 2 is in the number, it's always before digit 5. In other words, the code doesn't ever look at the number 52, only 25. Why? Because the smallest anagram number (numbers with the same digits in a different order) will always start with the smallest digit, then the second smallest, etc.
So, putting this all together:
void main(){
// Read in the target sum S
int S;
cin >> S;
// Set ans to be a value that's higher than anything possible
// Because the largest number with unique digits is 987654321.
int ans = 1e9;
// Go through each combination of digits, from 1 to 9.
for (int mask = 0; mask < 1 << 9; mask++) {
int sum = 0;
string num;
for (int i = 0; i < 9; i++)
// If this combination includes the digit i+1,
// Then add it to the sum, and append to the string representation.
if (mask >> i & 1) {
sum += i + 1;
num += char('0' + (i + 1));
}
// If this combination does not yield the right sum, try the next combination.
if (sum != S)
continue;
// If this combination does yield the right sum,
// see if it's smaller than our previous smallest.
ans = min(ans, stoi(num));
}
// Print the smallest combination we found.
cout << ans << '\n';
}
I hope this helps!
The for loop is iterating over all 9-digit binary numbers and turning those binary numbers into a string of decimal digits such that if nth binary digit is on then a n+1 digit is appended to the decimal number.
Generating the numbers this way ensures that the digits are unique and that zero never appears.
But as #Welbog mentions in comments this solution to the problem is way more complicated than it needs to be. The following will be an order of magnitude faster, and I think is clearer:
int smallest_number_with_unique_digits_summing_to_s(int s) {
int tens = 1;
int answer = 0;
for (int n = 9; n > 0 && s > 0; --n) {
if (s >= n) {
answer += n * tens;
tens *= 10;
s -= n;
}
}
return answer;
}
Just a quick way to on how code works.
First you need to know sum of which digits equal to S. Since each digit is unique, you can assign a bit to them in a binary number like this:
Bit number Digit
0 1
1 2
2 3
...
8 9
So you can check all numbers that are less than 1 << 9 (numbers with 9 bits corresponding 1 to 9) and check if sum of bits if equal to your sum based on their value. So for example if we assume S=17:
384 -> 1 1000 0000 -> bit 8 = digit 9 and bit 7 = digit 8 -> sum of digits = 8+9=17
Now that you know sum if correct, you can just create number based on digits you found.

How to solve Permutation of a phone number problem

The Problem:
A company is distributing phone numbers to its employees to make things easier. the next digit cannot be equal to the last is the only rule for example 0223 is not allowed while 2023 is allowed. At least three digits will be excluded every time. Write a function that takes in a length of the phone number and the digits that will be excluded. The function should print all possible phone numbers.
I got this question in an interview and I have seen one like it before at my university. It is a permutation problem. My question is what is the best way or decent way to solve this without a million for loops.
I do understand that this is technically how it works
length of phone number = 3;
[0-9], [0-9] excluding the last digit, [0-9] excluding the last digit
but I am unsure on how the best way to turn this into code. Any language is accepted!
thank you:
Also I might be asking this in the wrong place. please let me know if I am.
A simple way to solve this problem could be using Recursion. Here's my commented C++ code:
void solve(int depth, int size, vector <int> &curr_seq){
// If the recursion depth is equal to size, that means we've decided size
// numbers, which means that curr_seq.size() == size. In other words, we've
// decided enough numbers at this point to create a complete phone number, so
// we print it and return.
if(depth == size){
for(int item : curr_seq){
cout << item;
}
cout << "\n";
return;
}
// Try appending every possible digit to the current phone number
for(int i = 0; i <= 9; ++i){
// Make sure to only append the digit i if it is not equal to the last digit
// of the phone number. We can also append it, however, if curr_seq
// is empty (because that means that we haven't decided the 1st digit yet).
if(curr_seq.empty() || curr[curr.size() - 1] != i){
curr_seq.push_back(i);
solve(depth + 1, size, curr);
curr_seq.pop_back();
}
}
}
I think I like the recursive solution, but you can also just generate all permutations up to the limit (iterate), filter out any with repeating digits, and print the successful candidates:
#include <iomanip>
#include <iostream>
#include <sstream>
using namespace std;
// Because C/C++ still has no integer power function.
int ipow(int base, int exp) {
int result = 1;
for (;;) {
if (exp & 1)
result *= base;
exp >>= 1;
if (!exp)
return result;
base *= base;
}
}
void noconsec(const int len) {
int lim = ipow(10, len);
// For e.g. len 4 (lim 10000),
// obviously 00xx won't work, so skip anything smaller than lim / 100.
int start = (len <= 2) ? 0 : (lim / 100);
for (int num = start;num < lim;num++) {
// Convert to string.
std::stringstream ss;
ss << std::setw(len) << std::setfill('0') << num;
std::string num_s = ss.str();
// Skip any consecutive digits.
bool is_okay = true;
auto prev_digit = num_s[0];
for (int digit_idx = 1;digit_idx < num_s.length();digit_idx++) {
auto digit = num_s[digit_idx];
if (prev_digit == digit) {
is_okay = false;
}
prev_digit = digit;
}
// Output result.
if (is_okay) {
cout << num_s << "\n";
}
}
}
int main(const int argc, const char * const argv[]) {
noconsec(4);
}
Differences to note, this needs an integer power function to compute the limit. Converting an int to a string and then checking the string is more complex than constructing the string directly. I guess it could be useful if you have a list of integers already, but mostly I did it for fun.

How do I proceed with a question like this? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Good Evening everyone. I am not really sure as to whether it is against the rules to ask questions like these on this platform (If it is, kindly tell me). The question is of a "practice competition". I could complete 5 of 10 test cases but I am not sure what is wrong in this. Please suggest any correction/logic/hint... And Time Complexity must be less than O(n^2) (According to the input given)
The approach I tried is:
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
signed long int t, n;
scanf("%d", &t);
for (int i = 1; i <= t; i++) {
int count = 0;
scanf("%d", &n);
if (n <= 10)
count = n;
else {
// count = 9;
string s;
s = to_string(n);
int len = s.length();
int x = n / (pow(10, len - 2));
int h = x / 11;
string y = to_string(x);
if (y.length() <= 2)
x = 0;
count = (9 * (len - 1)) + x + h;
}
printf("%d\n", count);
}
return 0;
}
Please suggest whatever you feel is helpful. Thank you so much.
For the problem, given that the work area you are dealing with is relatively small (the number of beautiful numbers less than 10^9 can be reasonably handled with a table of those values), here is a version of a solution that uses a pre-generated table of all of the beautiful numbers in sorted order.
Once the table is set up, it is just a matter of doing a binary search to determine the number of beautiful numbers there are that occur before the input value. The position of the closest beautiful number in the table is the number of beautiful numbers we need.
The binary search is done by utilizing the <algorithm> function std::upper_bound. This function will return an iterator to the item that is greater than the search item. Then to get the position, std::distance is used (we subtract 1, since std::upper_bound will give us the item that is greater than the searched item).
The generation of the table can be done at compile-time (by hand, just initializing an array), or if you're lazy, generated at runtime with a simple loop. Here is one such solution:
#include <algorithm>
#include <vector>
#include <iostream>
std::vector<int> values;
int generate_value(int digit, int numTimes)
{
int total = 0;
for (int i = 0; i < numTimes; ++i)
total = 10 * total + digit;
return total;
}
// I'm lazy, so let the program generate the table for me
void generate_values()
{
size_t curIdx = 0;
values.push_back(0);
for (int i = 1; i <= 9; ++i)
{
for (int j = 1; j <= 9; ++j)
values.push_back(generate_value(j, i));
}
values.push_back(1111111111);
}
// does a binary search and returns the position of the beautiful number
int beautiful(int num)
{
if (num == 0)
return 1;
// get iterator to closest number equaling the beautiful number
auto iter = std::upper_bound(values.begin(), values.end(), num);
// get distance from beginning of vector
return std::distance(values.begin(), iter) - 1;
}
int main()
{
generate_values();
std::cout << beautiful(18) << "\n";;
std::cout << beautiful(1) << "\n";;
std::cout << beautiful(9) << "\n";;
std::cout << beautiful(100500) << "\n";;
std::cout << beautiful(33) << "\n";;
std::cout << beautiful(1000000000) << "\n";;
}
Output:
10
1
9
45
12
81
The size of the table is in total, 83 entries, thus a binary search of this table will take no more than log(83) checks to find the value, which is at most 7 probes in the table.
This is not a complex problem.
Assuming your input is correct so we don’t have to do any checking we observe:
If number n is single digit the number of beautiful numbers is b = n.
If number n is double digit and the first digit is f, then the number of beautiful numbers b = 9 + x, where x is a number of all beautiful double digit numbers smaller than n,
If number n is triple digit and the first digit is f, then the number of beautiful numbers b = 2 x 9 + x, where x is a number of all beautiful triple digit numbers smaller than n.
And so on and on
Thus we can extrapolate: If number n has d digits, than the number of beautiful numbers
s = (d-1) * 9 + x,
where x is a number of beautiful d-digit numbers smaller than or equal to n.
So your problem was reduced to finding x. And this can be reduced even further. Take for instance number n = 44437. The important number here is first digit f. It is trivial to see that all 5 digit beautiful numbers that begin where single digits are less then f are ok. In our example 11111, 22222, 33333 are ok, while 444444 and larger are not.
So all you need to do is to check if beautiful number fffff is smaller than or equal to n. And this can be done with simple traversal of input string.
So your solution would be:
s = (d-1) * 9 + (f-1) + supersecretsauce,
where:
s - solution
n – your input number of age
d – number of digits, assuming your input is always correct is length(n)
f – first digit of your number n
supersecretsauce – 1 if fff…f is smaller or equal than n, 0 if bigger.
And even the traversal of input string can be optimized, but I leave that to you.
Oh yeah... and the time complexity of this solution O(n) = length(n) = log10(n).
A couple of things about the early set up.
1) From the input example you gave, it appears the t and each n need to be input sequentially, but your code prints the number of beautiful numbers before the next input is received. I would suggest reading in t first, then looping through an array of size t to get all the inputs first.
2) The constraints aren't tested. I would test the t and each value in the array mentioned before that the constraints are met, and either have the user try again if they aren't, or simply abort.

solving project euler #4 with c++

Q.A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
this is my code .it worked for 2 digit problem and gave 9009 as answer but it is not working for 3 digit number part.
#include <iostream>
using namespace std ;
bool ispallin(int n)
{
int reverse = 0, temp;
temp = n;
while (temp != 0)
{
reverse = reverse * 10;
reverse = reverse + temp%10;
temp = temp/10;
}
if (n == reverse)
return true;
else
return false;
}
int main() {
int a[999*999]={0},i,j,no;//0 implies no. at i th position is pallindrome
for(i=100;i<1000;i++)
{
for(j=100;j<1000;j++)
{
if(a[i*j]==0)//no. is pallin
{
if(ispallin(i*j))
no=i*j;
else a[i*j]=1;//no. at this pos is not pallindrome
}
}
}
cout<<no;
return 0;
}
your code is very nice, i would add a little bit more comments or maybe meaningful names to the functions but it is good code, the answer isn't what you were looking for because you never made sure that the result is the highest there is.
maybe 700*700 would be a palindrome but then 701*600 would also be a palindrome, i your case once 'i' is bigger it will overwrite the result, even if the polindrom is a bigger one.

Given number N eliminate K digits to get maximum possible number

As the title says, the task is:
Given number N eliminate K digits to get maximum possible number. The digits must remain at their positions.
Example: n = 12345, k = 3, max = 45 (first three digits eliminated and digits mustn't be moved to another position).
Any idea how to solve this?
(It's not homework, I am preparing for an algorithm contest and solve problems on online judges.)
1 <= N <= 2^60, 1 <= K <= 20.
Edit: Here is my solution. It's working :)
#include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
string n;
int k;
cin >> n >> k;
int b = n.size() - k - 1;
int c = n.size() - b;
int ind = 0;
vector<char> res;
char max = n.at(0);
for (int i=0; i<n.size() && res.size() < n.size()-k; i++) {
max = n.at(i);
ind = i;
for (int j=i; j<i+c; j++) {
if (n.at(j) > max) {
max = n.at(j);
ind = j;
}
}
b--;
c = n.size() - 1 - ind - b;
res.push_back(max);
i = ind;
}
for (int i=0; i<res.size(); i++)
cout << res.at(i);
cout << endl;
return 0;
}
Brute force should be fast enough for your restrictions: n will have max 19 digits. Generate all positive integers with numDigits(n) bits. If k bits are set, then remove the digits at positions corresponding to the set bits. Compare the result with the global optimum and update if needed.
Complexity: O(2^log n * log n). While this may seem like a lot and the same thing as O(n) asymptotically, it's going to be much faster in practice, because the logarithm in O(2^log n * log n) is a base 10 logarithm, which will give a much smaller value (1 + log base 10 of n gives you the number of digits of n).
You can avoid the log n factor by generating combinations of n taken n - k at a time and building the number made up of the chosen n - k positions as you generate each combination (pass it as a parameter). This basically means you solve the similar problem: given n, pick n - k digits in order such that the resulting number is maximum).
Note: there is a method to solve this that does not involve brute force, but I wanted to show the OP this solution as well, since he asked how it could be brute forced in the comments. For the optimal method, investigate what would happen if we built our number digit by digit from left to right, and, for each digit d, we would remove all currently selected digits that are smaller than it. When can we remove them and when can't we?
In the leftmost k+1 digits, find the largest one (let us say it is located at ith location. In case there are multiple occurrences choose the leftmost one). Keep it. Repeat the algorithm for k_new = k-i+1, newNumber = i+1 to n digits of the original number.
Eg. k=5 and number = 7454982641
First k+1 digits: 745498
Best number is 9 and it is located at location i=5.
new_k=1, new number = 82641
First k+1 digits: 82
Best number is 8 and it is located at i=1.
new_k=1, new number = 2641
First k+1 digits: 26
Best number is 6 and it is located at i=2
new_k=0, new number = 41
Answer: 98641
Complexity is O(n) where n is the size of the input number.
Edit: As iVlad mentioned, in the worst case complexity can be quadratic. You can avoid that by maintaining a heap of size at most k+1 which will increase complexity to O(nlogk).
Following may help:
void removeNumb(std::vector<int>& v, int k)
{
if (k == 0) { return; }
if (k >= v.size()) {
v.clear();
return;
}
for (int i = 0; i != v.size() - 1; )
{
if (v[i] < v[i + 1]) {
v.erase(v.begin() + i);
if (--k == 0) { return; }
i = std::max(i - 1, 0);
} else {
++i;
}
}
v.resize(v.size() - k);
}