输出整数m中删除n位之后的最大(小)数(保持各位顺序不变)

这个题不知道ac没有,因为是随便看到的一个题,没办法测,如果有错误请帮我指出来~

看到很多复杂度很高的暴力破解方法,有三层循环的那种,我这个复杂度应该会低一点。

/*思路,先将结果初始化最后m-n个字符,放在res中
从res的第一位开始,在它前面寻找最大的字符,并且替换,将最大位的下标记为max
下一次从max开始寻找。由于max已经被用过,防止被重复使用,就在上一轮找到max之后将其置0
*/
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main() {
	string m;
	int n;
	cin >> m >> n;
	int len = m.length();

	vector<char> vec(len);
	for (int i = 0; i < m.length(); i++)
		vec[i] = m[i];

	int new_len = m.length() - n;
	vector<char> res(new_len);
	for (int i = len - new_len, j = 0; j < new_len; i++, j++)
		res[j] = vec[i];

	//从res的最高位开始,依次选取res前面的序列中最大的值,并赋给当前位,
	int max=0;//记录被选中的最大的值的下标,下次就从这里开始向后搜索,前面的不用搜索
	for (int i = 0; i < new_len; i++)
	{
		int flag = 1;
		for (int j = max; j < len - new_len+i; j++)//+i很重要
		{
			if (res[i] <= vec[j])
			{
				res[i] = vec[j];
				max = j;
				vec[max] = '0';//最大位重新置为0,下一次搜索从这里开始,但不能重复使用这一位
				flag = 0;
			}
		}
		if (flag) break;//flag为1说明i位在初始化的情况下,就是最大的。i后面的不用比较了
	}
	for (int i = 0; i < new_len; i++)
		cout << res[i];
	
	return 0;
}

例子:

还看到有另外一种情况,从m中删除n个数,使得到的序列最小(保持顺序不变)

同样可以使用这个思路,初始化,开始寻找时,也是从res[0]开始,但是每一轮应该从后往前找,找最小值。找到最小值后,下一轮必须在这个最小值的后面产生。

#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main() {
	string m;
	int n;
	cin >> m >> n;
	int len = m.length();

	vector<char> vec(len);
	for (int i = 0; i < m.length(); i++)
		vec[i] = m[i];

	int new_len = m.length() - n;
	vector<char> res(new_len);
	for (int i = len - new_len, j = 0; j < new_len; i++, j++)
		res[j] = vec[i];

	int min = -1 ;//记录这一轮找到的最小位位置
	int last = -1;//last的作用是记录这一轮找到的最小值位置,找下一轮的最小值时,只能在last之后找
	for (int i = 0; i < new_len; i++)
	{
		int flag = 1;
		for (int j = len-new_len-1+i; j > last; j--)
		{
			if (res[i] >= vec[j])
			{
				res[i] = vec[j];
				min = j;
				flag = 0;
			}
		}
		last = min;
		if (flag) break;
	}
	for (int i = 0; i < new_len; i++)
		cout << res[i];

	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_20613513/article/details/82262919