【時間複雜度】【貪心】最大新整數
阿新 • • 發佈:2019-01-05
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">【題目大意】</span>
現給定一個n位的整數,要求從其中刪去k個數,使得刪完後得到的數最大。
【樣例輸入】
5 2
25158
【樣例輸出】
558
【資料範圍】
1≤k≤nxi
-----------------------------------------------------------------------------------------------------
【分析】
非常經典的貪心:刪去第一個遞減區域的最後一個元素。
#include<cstdio> const int mn = 500000 + 5; char num[mn]; int h[mn]; int main() { freopen("game.in", "r" , stdin); freopen("game.out", "w", stdout); int n, m, i, j, k; scanf("%d%d", &n, &m); scanf("%s", num + 1); for(i = 1; i <= n; i++) h[i] = num[i] - '0'; for(i = 1; i <= m; i++) { for(j = 1; j <= n; j++) { if(h[j] != 10) { for(k = j - 1; k > 0 && h[k] == 10; k--); if(k && h[j] > h[k]) { h[k] = 10; break; } } if(j == n) { for(; h[j] == 10; j--); h[j] = 10; break; } } } for(i = 1; i <= n; i++) { if(h[i] < 10) printf("%d", h[i]); } }
上述方法的時間複雜度為O(mn^2)。再看看這道題的資料規模……唉,說起來都是滿臉的淚啊!
-------------------------------------------------------------------
細細分析,我們可以發現,上面的程式碼將很多地方重複遍歷了很多遍。那能不能不遍歷那些地方?此時,我們可以用一個棧來優化:
1、依次將每個數壓入棧。
2、每次壓入棧之前,比較棧頂元素和壓人元素。
如果棧頂≥壓入,執行1
否則,將棧頂彈出,繼續比較。
3、輸出前n-k個數
按此法優化的程式碼的時間複雜度為O(n) (^_^+)。
#include<cstdio>
const int mn = 500000 + 5;
char num[mn];
int h[mn], ans[mn];
int main()
{
freopen("game.in", "r" , stdin);
freopen("game.out", "w", stdout);
int n, m, i, sum = 0;
scanf("%d%d", &n, &m);
scanf("%s", num + 1);
for(i = 1; i <= n; i++)
h[i] = num[i] - '0';
int top;
ans[1] = h[1];
for(i = 2, top = 1; i <= n && sum < m; i++)
{
while(ans[top] < h[i] && top && sum < m)
{
ans[top] = 0;
top--, sum++;
}
top++;
ans[top] = h[i];
}
for(top++; i <= n; i++, top++)
ans[top] = h[i];
if(!ans[1])
printf("0");
else
{
for(i = 1; i <= n - m; i++)
printf("%d", ans[i]);
}
}