Leetcode题解:用字符串快速解决Create Maximum Number问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jining11/article/details/84311064

问题描述

Given two arrays of length m and n with digits 0-9 representing two numbers. 
Create the maximum number of length k <= m + n from digits of the two. 
The relative order of the digits from the same array must be preserved. 
Return an array of the k digits.

Note: You should try to optimize your time and space complexity.

Example 1:

Input:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
Output:
[9, 8, 6, 5, 3]
Example 2:

Input:
nums1 = [6, 7]
nums2 = [6, 0, 4]
k = 5
Output:
[6, 7, 6, 0, 4]
Example 3:

Input:
nums1 = [3, 9]
nums2 = [8, 9]
k = 3
Output:
[9, 8, 9]

算法设计

可以分成三大部分来考虑,首先是分别从两个向量中提取长度为x的最大数字s1和长度为k-x的最大数字s2,之后是要将s1和s2合并成为最大的数字s3,最后是从所有可能的s3当中,抽取最大的那一个,并转换成vector返回。

主要思想:

  • 从向量中提取某长度的最大数字使用了贪心法,因为只要一个数字的高位比另一个数字高,就一定比它要大,因此可以使用栈来不断更新高位的值。
  • 将两个字符串合并使用了类似归并排序的思路,每次都看两个字符串的第一个元素的值谁更大。但要注意由于字符串并非是内部有序的,因此在遇到相等的情况时要一直往后找来决定选择哪一个。

代码实现

class Solution {
public:

	//从num里面求取长为k的最大值
	string get_maxnum (vector<int>& num, int k) {
		string v = "";
		char c;
		if (k == 0) {
			return v;
		}
		v.resize(k);
		v[0] = char(num[0]+'0');
		int j = 1;
		for (int i = 1; i < num.size(); i++) {
			c = char(num[i]+'0');
			if (c > v[j-1]) {
				while (c > v[j-1] && num.size()-i+j > k && j > 0) {
					j--;
				}
			}
			if (j < k) {
				j++;
				v[j-1] = c;
			}
		}
		return v;
	}

	//获取两个向量按序能够组成的最长的串
	string maxnumber(string nums1, string nums2) {
		string s = "";
        int m = nums1.size();
        int n = nums2.size();
        int i = 0, j = 0;
        for (; i < m && j < n;) {
        	if (nums1[i] > nums2[j]) {
        		s += nums1[i];
        		i++;
        	}
        	else if (nums1[i] < nums2[j]) {
        		s += nums2[j];
        		j++;
        	}
        	else {
        		int ii = i, jj = j;
        		for(;;ii++,jj++) {
        			if (nums1.size() == ii || nums2[jj] > nums1[ii]) {
        				jj = ii+1;
        				break;
        			}
        			if (nums2.size() == jj || nums2[jj] < nums1[ii]) {
        				ii = jj+1;
        				break;
        			}
        		}
        		if (ii > jj) {
	        		s += nums1[i];
	        		i++;
	        	}
	        	else {
	        		s += nums2[j];
	        		j++;
	        	}
        	}
        }
        return s+nums1.substr(i)+nums2.substr(j);
    }

    vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
        int m = nums1.size();
        int n = nums2.size();
        string max = "";
        int mm = m > k ? k:m;
        int nn = n > k ? k:n;
        string temp;
        for (;mm >= 0; mm--) {
        	if (mm == k) {
        		temp = get_maxnum(nums1, mm);
        	}
        	else {
        		if (k-mm <= nn) {
        			temp = maxnumber(get_maxnum(nums1, mm), get_maxnum(nums2, k-mm));
        		}
        		else {
        			break;
        		}
        	}
        	max = max < temp ? temp:max;
        }
        for (;nn >= 0; nn--) {
            if (nn == k) {
                temp = get_maxnum(nums2, nn);
            }
            else {
                if (k-nn <= mm) {
                    temp = maxnumber(get_maxnum(nums2, nn), get_maxnum(nums1, k-nn));
                }
                else {
                    break;
                }
            }
            max = max < temp ? temp:max;
        }
        std::vector<int> v;
        for (auto c:max) {
        	v.push_back(c-'0');
        }
        return v;
    }
};

这次被一个无比智障的bug坑了很久,就是我居然直接拿数字和字符比较,然后就得到了9 < '0’这种无比神奇的结果。不过也有收获,第一次用了string的resize方法。本来以为这个算法笨重无比,但最后居然结果还不错。。。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/jining11/article/details/84311064
今日推荐