算法:(贪心算法)--删数问题


删数问题(需知道的数学定理)

给定n位正整数a,去掉其中任意k≤n 个数字后,剩下的数字按原次序排列组成一个新 的正整数。对于给定的n位正整数a和正整数 k,设计一个算法找出剩下数字组成的新数最 小的删数方案。

定理: ex:1 2 3 9 5;删掉一个数;

从第一个数开始遍历,到寻找到单调递减的第一个数(即单调递增的最后一个数),则删除,若无单调递减子序列,则删掉最后一个非递减序列的数;每找到一个就又从头开始。即每做一次删数,就是一次贪心选择,删掉此数剩下的数为组成最小,经过证明,此结论正确。

ex:1 2 3 9 5,删掉三个数;

1:1 2 3 5

2:1 2 3

3:1 2


注意一种情况:3 0 0 2,删去一个数;

应该是2,而不是002

Input

     
 
第 1 行是1 个正整数 a。第 2 行是正整数k。
 
     

Output

     
 
输出最小数
 
     

Sample Input

     
 
178543 
4 
 
     

Sample Output

     
 
13
 
 


#include<iostream>;
#include<cstring>;
using namespace std;

int shanshu(char *a,int k) {
	int n = strlen(a);
	while (k > 0) {//每次删一个数,使得剩下的数按原序列组成最小。
		for (int i = 0; i < n; i++) {
			if (i == n - 1) {
				n--;
				break;
			}//没找到那个单调递减的第一个数,就删掉非递减序列的最后一个数。
			else if (a[i] > a[i + 1]) {
				for (int j = i; j < n - 1; j++) {
					a[j] = a[j + 1];//删掉一个,后面的全部前移一位。
				}
				n--;//长度减一
				break;
			  }
			}
		k--;
	}
	return n;

}

int main() {
	char* input = new char();//char类型数组
	cin >> input;
	//cout << input[1];是一个数组。
	//cout << strlen(input);可以这样获得长度:strlen
	int k;
	cin >> k;
	int m = shanshu(input, k);
	int b = 0;
	while((b<(m-1))&&(input[b]=='0'))b++;	//注意是char,所以不能是0,一定是'0'。		
	//处理上述注意的情况,即002这种情况
	for (int i = b; i < m; i++) {
		cout << input[i];
	}
	system("pause");
	return 0;
}
点赞