练习题 拼接最大数

发布时间:2024年01月18日
题目

给定长度分别为?m?和?n?的两个数组,其元素由?0-9?构成,表示两个自然数各位上的数字。现在从这两个数组中选出?k (k <= m + n)?个数字拼接成一个新的数,要求从同一个数组中取出的数字保持其在原数组中的相对顺序

求满足该条件的最大数。结果返回一个表示该最大数的长度为?k?的数组。

说明:?请尽可能地优化你算法的时间和空间复杂度。

示例?1:

输入:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
输出:
[9, 8, 6, 5, 3]

示例 2:

输入:
nums1 = [6, 7]
nums2 = [6, 0, 4]
k = 5
输出:
[6, 7, 6, 0, 4]

示例 3:

输入:
nums1 = [3, 9]
nums2 = [8, 9]
k = 3
输出:
[9, 8, 9]
提交代码
//拼接最大数

//求满足条件的最大数
//最大数特点:相同组成的情况下,尽可能的把大数放前面
//最大数的位数已定
//从前往后,前面的数越大的越大 
//两个数组拼接
//需要借助分治,假设从两个数组中需要取几个 
//改良后的单调栈->栈顶的元素应该更小(注意剩的位数够不够) 

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

vector<int> nums1;//数组1 
vector<int> nums2;//数组2
int k;//最终整数数组的位数
vector<int> result;//最终整数数组 
stack<int> stk1,stk2;//单调栈
vector<int> t1,t2;//存单调栈中的元素 
stack<int> eq;//存相等的栈顶 
int n1,n2;//两个数组长度
string maxStr = "0";//记录当前最大的整数
string res;
int cnt;//单调栈和数组中剩下的元素和
int inStack;//单调栈里元素个数 

//单调栈
void monotonicStack1(int p,int k1){
	while(!stk1.empty()){
		if(stk1.top() < nums1[p] && cnt > k1){
			stk1.pop();
			cnt--;
			inStack--;
		}else{
			break;
		}
	}
	
	//栈里的元素不能超过k1个
	if(inStack < k1){
		stk1.push(nums1[p]);
		inStack++;
	}else{
		cnt--;
	}
} 

void monotonicStack2(int p,int k2){
	while(!stk2.empty()){
		if(stk2.top() < nums2[p] && cnt > k2){
			stk2.pop();
			cnt--;
			inStack--;
		}else{
			break;
		}
	}
	
	//栈里的元素不能超过k2个
	if(inStack < k2){
		stk2.push(nums2[p]);
		inStack++;
	}else{
		cnt--;
	}
} 

//分治找各个情况下的
/*void divide(int k1,int k2){
	//找第一个数组的元素
	//单调栈 
	cnt = n1;
	inStack = 0; 
	for(int i = 0;i < n1;i++){
		monotonicStack1(i,k1);
	} 
	
	//找第二个数组的元素
	//单调栈
	cnt = n2;
	inStack = 0;
	for(int i = 0;i < n2;i++){
		monotonicStack2(i,k2);
	} 
	
	//弹出合并两个栈中的内容
	//注意弹出的内容是反向的
	while(!stk1.empty()){
		//cout << stk1.top();
		t1.push(stk1.top());
		stk1.pop();
	}
	//cout<<endl;
	while(!stk2.empty()){
		//cout << stk2.top();
		t2.push(stk2.top());
		stk2.pop();
	}
	//cout<<endl;
	
	while(!t1.empty() && !t2.empty()){
		//逻辑错误
		int last = -1; 
		while(!t1.empty() && !t2.empty() && t1.top() == t2.top() && last < t1.top()){
			//如果两个栈顶相等,判断下一个哪个更大
			//cout<<t1.top();
			last = t1.top();
			res += to_string(t1.top());
			eq.push(t1.top());
			t1.pop();
			t2.pop();
		}
		
		if(t1.empty()){
			while(!eq.empty()){
				t1.push(eq.top());
				eq.pop();
			}
			continue;
		}else if(t2.empty()){
			while(!eq.empty()){
				t2.push(eq.top());
				eq.pop();
			}
			continue;
		}
		
		//将相等的元素放回
		if(t1.top() > t2.top()){
			while(!eq.empty()){
				t2.push(eq.top());
				eq.pop();
			}
		}else if(t1.top() < t2.top()){
            while (!eq.empty()) {
                t1.push(eq.top());
                eq.pop();
            }
        }else{
            continue;
        }
		
		if(t1.top() > t2.top()){
			//cout<<t1.top();
			res += to_string(t1.top());
			t1.pop();
		}else if(t1.top() < t2.top()){
			//cout<<t2.top();
			res += to_string(t2.top());
			t2.pop();
		}
	}
	
	while(!t1.empty()){
		//cout<<t1.top();
		res += to_string(t1.top());
		t1.pop();
	}
	while(!t2.empty()){
		//cout<<t2.top();
		res += to_string(t2.top());
		t2.pop();
	}
	
	//cout<<endl;
	
	//maxStr = max(res,maxStr);
	maxStr = maxStr > res ? maxStr : res;
	
	//cout<<res<<endl;

	//清空字符串
	res = "";
}*/
//改用数组合并,逻辑更清楚
void divide(int k1,int k2){
	//找第一个数组的元素
	//单调栈 
	cnt = n1;
	inStack = 0; 
	for(int i = 0;i < n1;i++){
		monotonicStack1(i,k1);
	} 
	
	//找第二个数组的元素
	//单调栈
	cnt = n2;
	inStack = 0;
	for(int i = 0;i < n2;i++){
		monotonicStack2(i,k2);
	} 
	
	//弹出合并两个栈中的内容
	//注意弹出的内容是反向的
	while(!stk1.empty()){
		//cout << stk1.top();
		t1.push_back(stk1.top());
		stk1.pop();
	}
	//cout<<endl;
	while(!stk2.empty()){
		//cout << stk2.top();
		t2.push_back(stk2.top());
		stk2.pop();
	}
	//cout<<endl;
	
	//反转
	reverse(t1.begin(),t1.end());
	reverse(t2.begin(),t2.end());
	
	/*for(int i = 0;i < k1;i++){
		cout<<t1[i];
	}
	cout<<endl;
	for(int j = 0;j < k2;j++){
		cout<<t2[j];
	}
	cout<<endl;*/
	
	int p1 = 0,p2 = 0;//两个数组的遍历指针 
	
	while(p1 < k1 && p2 < k2){
		if(t1[p1] > t2[p2]){
			res += to_string(t1[p1]);
			p1++;
		}else if(t1[p1] < t2[p2]){
			res += to_string(t2[p2]);
			p2++;
		}else{
			//两个元素相等时
			res += to_string(t1[p1]);
			//找下一个不相等的元素
			int i = p1 + 1,j = p2 + 1;
			
			if(i == k1){
				//数组1空了
				p2++; 
				continue;
			}else if(j == k2){
				//数组2空了
				p1++; 
				continue;
			}
			
			for(;i < k1,j < k2;i++,j++){
				if(t1[i] > t2[j]){
					p1++;
					break;
				}else if(t1[i] < t2[j]){
					p2++;
					break;
				}else{
					if(i == k1 - 1){
						//数组1要空了
						p2++; 
					}else if(j == k2 - 1){
						//数组2要空了
						p1++; 
					}
				}
			}
		}
	}
	
	while(p1 < k1){
		res += to_string(t1[p1]);
		p1++;
	}
	
	while(p2 < k2){
		res += to_string(t2[p2]);
		p2++;
	}
	
	//cout<<endl;
	
	//maxStr = max(res,maxStr);
	maxStr = maxStr > res ? maxStr : res;
	
	//cout<<res<<endl;

	//清空字符串
	res = "";
}

int main(){
	//输入整数数组  
	int t; 
	
	while(cin.peek() != '\n'){
		scanf("%d",&t);
		nums1.push_back(t);
	}
	
	//删掉输入流中的回车符
	cin.ignore(1,'\n'); 
	
	while(cin.peek() != '\n'){
		scanf("%d",&t);
		nums2.push_back(t);
	}
	
	//删掉输入流中的回车符
	cin.ignore(1,'\n'); 
	
	//输入位数
	scanf("%d",&k);
	
	//-------------------------------
	
	n1 = nums1.size();//数组1长度
	n2 = nums2.size();//数组2长度
	
	//分治
	for(int i = 0;i <= k;i++){
		if(i > n1){
			break;
		}
		
		//printf("i=%d\n",i);
		
		if(k - i <= n2){
			//找各个情况下的
			divide(i,k - i);
		}
	} 
	
	//结果转换为数组
	string s;
	for(int i = 0;i < k;i++){
		//存在二义性,应该先将各个字符转换为字符串 
		//result.push_back(stoi(maxStr[i]));
		//防止maxStr[i]中含有非数字的字符 
		if(isdigit(maxStr[i])){
			s = string(1,maxStr[i]);
			result.push_back(stoi(s));
		}
	}
	
	//输出结果
	for(int i = 0;i < k;i++){
		printf("%d",result[i]);
	}
	
	return 0;
} 
?总结

解题思路:要求的最大数的位数一定,需要从两个数组中选数,所以需要用分治考虑不同分配的情况。在每种分治的情况下,可以用改良后的单调栈来选取每个数组中要选取的数,要尽可能先选取更大的数(栈顶的元素要更小)且要保证单调栈中最终的元素个数。

注意:

? ? ? ? 字符串->整型:to_string(string str);

? ? ? ? ? ? ? ? to_string()不能将字符转换为整型,如遇字符,需要先用string(1,char c);将字符转换为字符串。

? ? ? ? 整型->字符串:stoi(int i);

????????

? ? ? ? 思路清楚最重要!!!

文章来源:https://blog.csdn.net/m0_64219374/article/details/135671375
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。