letecode 编程学习(21)

题目

给定长度分别为 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]

解题思路

  • 将这个题目转换成从两个序列中抽取k1 和 k2个数(每个序列中抽取的数保持原有的前后顺序),k1+k2=k。
  • 将提取的两组序列采用归并排序的思想进行合并。唯一需要考虑两个数相同的情况。
  • 将这k种中取最大的那一个。

单个序列取k个最大的序列可以利用栈的思想,栈顶小于当前的元素就出栈,直到栈顶元素大于当前元素就把当前元素入栈。

代码

class Solution {
public:
	vector<int> getMaxSeq(const vector<int>& nums1, int k)
	{
		vector<int> out;
		if (nums1.size() < k)
		{
			return out;
		}

		int m = nums1.size() - k;
		
		if (k == 0)
		{
			return out;
		}

		for (int i = 0; i < nums1.size(); i++)
		{
			while (m && out.size()> 0 && out[out.size() - 1] < nums1[i])
			{
				out.pop_back();
				m = m - 1;
			}
			out.push_back(nums1[i]);
		}

		return std::vector<int>(out.begin(), out.begin() + k);
	}

	

	bool bComBigger(const std::vector<int> &sq1, const std::vector<int> &sq2)
	{
		int maxLen = std::max(sq1.size(), sq2.size());
		int minLen = std::min(sq1.size(), sq2.size());
	
		for (int i = 0; i < minLen; i++)
		{
			if (sq1[i] >  sq2[i])
			{
				return false;
			}
			else if (sq1[i] <  sq2[i])
			{
				return true;
			}

		}

		if (sq1.size() < sq2.size())
		{
			return true;
		}

		return false;
	}

	bool bComBiggerOrg(const std::vector<int> &sq1, const std::vector<int> &sq2)
	{
	
		if (sq1.size() < sq2.size())
		{
			return true;
		}
		else if (sq1.size() > sq2.size())
		{
			return false;
		}



		for (int i = 0; i < sq1.size(); i++)
		{
			if (sq1[i] >  sq2[i])
			{
				return false;
			}
			else if (sq1[i] <  sq2[i])
			{
				return true;
			}

		}

	

		return false;
	}

	vector<int> merge(const vector<int>& nums1, const vector<int>& nums2)
	{
		vector<int> out(nums1.size() + nums2.size());
		int k = 0;
		int i = 0;
		int j = 0;

		while (i < nums1.size() && j < nums2.size())
		{
			if (nums1[i] > nums2[j])
			{
				out[k++] = nums1[i++];
			}
			else if (nums1[i] < nums2[j])
			{
				out[k++] = nums2[j++];
			}
			else
			{

				bool flag = bComBigger(std::vector<int>(nums1.begin() + i, nums1.end()), std::vector<int>(nums2.begin() + j, nums2.end()));
				if (flag)
				{
					out[k++] = nums2[j++];
				}
				else
				{
					out[k++] = nums1[i++];
				}
			}

		}

		while (i < nums1.size())
		{
			out[k++] = nums1[i++];
		}

		while (j < nums2.size())
		{
			out[k++] = nums2[j++];
		}

		return out;
	}
	vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {

		std::vector<int> out;
		for (int i = 0; i <= k; i++)
		{
			std::vector<int> sq1 = getMaxSeq(nums1, i);
			std::vector<int> sq2 = getMaxSeq(nums2, k - i);

			std::vector<int> sq = merge(sq1, sq2);

			if (bComBiggerOrg(out, sq))
			{
				out = std::move(sq);
			}
		}

		return out;
	}
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值