PAT甲级 1038. Recover the Smallest Number (30)

本文介绍了一个算法问题,即如何从给定的数字片段集合中恢复出最小可能的数字。通过自定义字符串比较逻辑来实现这一目标,并详细解释了处理各种边界情况的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

Given a collection of number segments, you are supposed to recover the smallest number from them. For example, given {32, 321, 3214, 0229, 87}, we can recover many numbers such like 32-321-3214-0229-87 or 0229-32-87-321-3214 with respect to different orders of combinations of these segments, and the smallest number is 0229-321-3214-32-87.

Input Specification:

Each input file contains one test case. Each case gives a positive integer N (<=10000) followed by N number segments. Each segment contains a non-negative integer of no more than 8 digits. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the smallest number in one line. Do not output leading zeros.

Sample Input:
5 32 321 3214 0229 87
Sample Output:
22932132143287
思路:

不能简单地用字符串比较函数,需要重载。其中针对两个字符串需要按位比较,位数不够时,将较短的字符串从头开始比较。例如,321与32比较,先是32与32比较,再是32中的3与321中的1进行比较。

在输出时,需注意开头为0 的情况,这其中还分

1)第一部分字符开头为0但还有其他数字,如0234-456-9,输出时为2344569

2)第一部分字符全为0,例如000-0120-3,输出时显示1203

3)前面一部分字符为0,例如00-000-120-3,输出显示1203

4)所有字符都为0,例如00-000-0000,输出显示0,这个是测试点2

代码:

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

bool comp1(const string &s1, const string &s2)
{
	//默认s1长于s2
	int L = s2.size();
	int m = s1.size() / L;
	int i, j, n1, n2;
	for (i = 0; i < m; ++i)
	{
		for (j = 0; j <L; ++j)
		{
			if (s1[i*L + j] != s2[j])
				return s1[i*L + j] < s2[j];
		}
	}
	i = m*L ;
	j = 0;
	while (i < s1.size() && j < s2.size())
	{
		if (s1[i] != s2[j])
		{
			return s1[i] < s2[j];
		}
		else
		{
			++i; ++j;
		}
	}

};
//比较函数
bool comp(const string &s1, const string &s2)
{
	if (s1 == s2)
		return s1 < s2;
	else
	{
		if (s1.size() > s2.size())
		{
			return comp1(s1, s2);
		}
		else
		{
			return !comp1(s2, s1);
		}
	}
};




int main()
{
	
	int N;
	cin >> N;
	vector<string> seg(N);
	for (int i = 0; i < N; ++i)
	{
		cin >> seg[i];
	}
	//排序
	sort(seg.begin(),seg.end(),comp);
	//输出
	string s;
	int k;
	bool flag = 0;
	for (int i = 0; i < N; ++i)
	{
		s = seg[i];		
		if (!flag)     //只针对开头无输出的情况
		{   k = 0;
			while (k < s.size())
			{
				if (s[k] > '0')
				{
					break;
				}
				++k;
			}
			if (k > 0) //开头有0
			{
				if (k == s.size())  //数字为0
				{	
					if (i == N-1)   //全为0的情况
					{
						cout << 0;
					}
				}
					
				while (k < s.size())//不为0的部分输出
				{
					cout << s[k];
					++k;
					flag = 1;
				}
				
			}
			else
			{
				flag = 1;
				cout << s;
			}
		}
		else
		{
			//开头有输出
			cout << s;
		}
	}
	cout << endl;
	system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值