正如标题所说,任务是:
给定数字N
消除K
位数以获得最大可能数量。数字必须保持在他们的位置。
示例:n = 12345
,k = 3
,max = 45
(前三位数字被删除,数字不得移动到其他位置)。
知道如何解决这个问题吗? (这不是家庭作业,我正准备进行算法竞赛并解决在线评委的问题。)
1 <= N <= 2^60
,1 <= K <= 20
。
编辑:这是我的解决方案。它的工作原理:))
#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;
}
答案 0 :(得分:3)
蛮力应该足够快以适应您的限制:n
将有最多19
位数字。使用numDigits(n)
位生成所有正整数。如果设置了k
位,则删除与设置位对应的位置的数字。将结果与全局最优值进行比较,并根据需要进行更新。
复杂性:O(2^log n * log n)
。虽然这似乎与O(n)
渐近相似,但在实践中它会更快,因为O(2^log n * log n)
中的对数是10的对数,这将给出更小的值(log base 10
的1 + n
为您提供n
的位数。
您可以通过一次生成log n
n
n - k
组合的组合来避免n - k
因素,并在生成每个given n, pick n - k digits in order such that the resulting number is maximum
时生成由所选d
个位置组成的数字组合(将其作为参数传递)。这基本上意味着您解决了类似的问题:{{1}})。
注意:有一种方法可以解决这个问题,但这并不涉及蛮力,但我也想向OP展示这个解决方案,因为他在评论中询问了如何强制执行。对于最佳方法,请研究如果我们从左到右逐位构建数字会发生什么,并且对于每个数字{{1}},我们将删除所有当前选定的小于它的数字。我们什么时候可以删除它们,什么时候不能删除它们?
答案 1 :(得分:3)
在最左边的k + 1个数字中,找到最大的一个(假设它位于第i个位置。如果有多个事件,请选择最左边的一个)。收下。重复k_new = k-i + 1,newNumber = i + 1的算法到原始数字的n位数。
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
复杂度为O(n),其中n是输入数字的大小。
编辑:正如iVlad所说,在最坏的情况下,复杂性可能是二次的。你可以通过保持最大k + 1的堆大小来避免这种情况,这会增加O(nlogk)的复杂性。
答案 2 :(得分:1)
以下可能会有所帮助:
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);
}