1. 程式人生 > >【時間複雜度】【貪心】最大新整數

【時間複雜度】【貪心】最大新整數

<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]);
	}
}