Reputation: 123
Given a number, we have to find the maximum 'K' digit number while preserving the order ( 'K' digit number will be a subsequence ).
Input : The number 'n' and number of digits you should pick up to form the answer 'K'
Output : The maximum formed K digit number
Example :
Input : n = 912583, k=3
Output : 983
Upvotes: 1
Views: 2019
Reputation: 1
I stumbled upon this (this forms part of the solution) while solving https://leetcode.com/problems/create-maximum-number/description/ As Matt pointed in his answer, a greedy strategy is good enough. Here is complete C++ program with a driver. n = 78859 and k = 3 outputs 889
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
template <typename IIT, typename OIT>
void
MaxNumPreservingOrder(IIT first, IIT last, OIT output, int k) {
if (k == 0)
return;
auto N = distance(first, last);
if (N == k) {
copy(first, last, output);
return;
}
auto it = first;
while (k > 0) {
auto maxval = *max_element(it, last - k + 1);
it = find(it, last - k + 1, maxval);
*output = *it;
++output;
++it;
--k;
}
return;
}
int
main(void) {
vector< int > v = {7, 8, 8, 5, 9}, o;
int k = 3;
o.reserve(k);
MaxNumPreservingOrder(begin(v), end(v), back_inserter(o), k);
copy(begin(o), end(o), ostream_iterator< int >(cout, " "));
cout << "\n";
return 0;
}
Upvotes: 0
Reputation: 2877
It can be solved by dynamic programming. You need the state dp[i][j]
, which is the optimal value when you choose j
digits from the first i-1
digits. Then you can solve it:
void solve(int n, int k) {
string str = string(n);
int dp[32][32];
memset(dp, 0, sizeof(dp));
for (size_t i = 0; i < str.length(); ++i) {
dp[i + 1][1] = max(dp[i][1], str[i] - '0');
for (size_t j = 2; j <= k; ++j) {
dp[i + 1][j] = max(dp[i][j - 1] * 10 + str[i] - '0', dp[i][j]);
}
}
cout << dp[str.length][k];
}
Upvotes: 0
Reputation: 551
Here's my solution just so that there is a code answer here (I found the question interesting enough to work it out). Basically I just find the first largest digit that still has enough trailing numbers to fill out the requisite length, and then repeats the problem recursively for the substring after that first largest digit (basically what Matt Timmermans suggested). I tested this a bit so I think it is complete and doesn't have any glaring bugs, but I may definitely have missed an edge case.
I realize that this is probably not the fastest I could make this algorithm since I am doing a lot of variable casting from int to string and back, but since it is a relatively small input size I figured I wouldn't worry about it unless someone wants me to.
Note: It returns 0 in cases where the inputs don't make sense like if the requested length is longer than the input.
private int GetMaximumNumber(int input, int length)
{
input = Math.Abs(input);
var maximumNumber = 0;
var inputString = input.ToString();
if (length > inputString.Length || length < 1)
return maximumNumber;
var indexOfMaxDigit = FindMaximumDigit(input, length);
var maxDigit = int.Parse(inputString.Substring(indexOfMaxDigit, 1));
if (length > 1)
maximumNumber = (maxDigit * (int)(Math.Pow(10.0, (double)length-1))) + GetMaximumNumber(int.Parse(inputString.Substring(indexOfMaxDigit + 1)), length - 1);
else
maximumNumber = maxDigit;
return maximumNumber;
}
private int FindMaximumDigit(int input, int length)
{
var indexOfMaxDigit = -1;
var inputSubstring = input.ToString().Substring(0, input.ToString().Length - length + 1);
for (var i = 9; i > -1; i--)
{
indexOfMaxDigit = inputSubstring.IndexOf(i.ToString(), StringComparison.Ordinal);
if (indexOfMaxDigit != -1)
break;
}
return indexOfMaxDigit;
}
Upvotes: 0
Reputation: 59154
You don't actually need dynamic programming to solve this problem. The largest K-digit number will always start with the largest possible digit, and it's always best to choose the earliest possible occurrence of the largest possible digit, because that leaves the most options open for the remaining digits.
Similarly, the best second digit is the earliest occurrence of the largest possible second digit, etc., until you're done.
Dynamic programming is used when the locally best choice (like earliest occurrence of the largest possible digit) isn't always the globally best choice.
Upvotes: 2