[英]Given number N eliminate K digits to get maximum possible number
正如標題所說,任務是:
給定數量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;
}
蠻力應該足夠快,以滿足你的限制: n
將有最多19
位數。 使用numDigits(n)
位生成所有正整數。 如果設置了k
位,則刪除與設置位對應的位置的數字。 將結果與全局最優值進行比較,並根據需要進行更新。
復雜性: O(2^log n * log n)
。 雖然這似乎與O(n)
漸近相似,但在實踐中它會更快,因為O(2^log n * log n)
中的對數是10對數的基數,這將給出一個小得多的值(1 + log base 10
的n
給你的位數n
)。
您可以通過一次生成n
取n - k
組合來避免log n
因子,並在生成每個組合時構建由所選n - k
位置組成的數字(將其作為參數傳遞)。 這基本上意味着你解決了類似的問題: given n, pick n - k digits in order such that the resulting number is maximum
)。
注意:有一種方法可以解決這個問題,但這並不涉及蠻力,但是我也希望向OP展示這個解決方案,因為他在評論中詢問了如何強制執行。 對於最佳方法,研究如果我們從左到右逐位數字構建我們的數字會發生什么,並且對於每個數字d
,我們將刪除所有當前選擇的小於它的數字。 什么時候我們可以刪除它們,何時不能刪除它們?
在最左邊的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)的復雜性。
以下可能有所幫助
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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.