【贪心】【位运算】【数组】
2605. 从两个数字数组里生成最小数字
给定两个各自只包含数字 1
到 9
的两个数组,每个数组中的元素互不相同,请你返回最小的数字,这个数字的数位至少包含两个数组中的数字。
贪心的思想,如果两个数组有交集,则答案为交集中的最小值;否则,需要找出各个数组中的最小值,用最小值组成最小答案。
我们先来讲述最小值的计算,方法有很多,可以先升序排序(降序排序)再返回首位置元素(末位置元素),还可以直接使用 API *min_element()
来计算数组中的最小值。
计算两个数组的交集有以下两种方法:
枚举所有可能的数字组合,如果该组合中的两个数字一样,则加入到交集 section
中,如果集合 section
非空,则返回集合中的最小值。
实现代码
class Solution {
public:
int minNumber(vector<int>& nums1, vector<int>& nums2) {
vector<int> section;
for (int i = 0; i < nums1.size(); ++i) {
for (int j = 0; j < nums2.size(); ++j) {
if (nums1[i] == nums2[j]) {
section.push_back(nums1[i]);
}
}
}
if (!section.empty()) {
return *min_element(section.begin(), section.end());
}
int min1 = *min_element(nums1.begin(), nums1.end());
int min2 = *min_element(nums2.begin(), nums2.end());
return min(min1 * 10 + min2, min2 * 10 + min1);
}
};
复杂度分析
时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn), n n n 为最大的数组长度。
空间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)。
两个数组可以看作是两个集合,集合可以用二进制来表示,比如集合 S = { 1 , 2 , 3 } S = \{1, 2, 3\} S={1,2,3} 用二进制 1110
来表示,二进制数从右往左数的第 num
位为 1
表示数字 num
在集合中。
于是数组的交集就可以使用集合的交集来表示,交集可以用二进制的与操作计算,然后与操作得到的二进制数从右到左找到第一个 1
的位置,即为两个数组交集中的最小值,这里我们可以使用 __builtin_ctz()
来查找从右至左第一个 1
出现的位置。
关于集合用运算来表示,如果还有不明白的地方可以参考 位运算基础与应用 这篇文章。
实现代码
class Solution {
public:
int minNumber(vector<int>& nums1, vector<int>& nums2) {
// 位运算
int mask1 = 0, mask2 = 0;
for (int x : nums1) mask1 |= 1 << x;
for (int x : nums2) mask2 |= 1 << x;
int mask = mask1 & mask2;
if (mask) return __builtin_ctz(mask);
int x = __builtin_ctz(mask1), y = __builtin_ctz(mask2);
return min(x * 10 + y, 10 * y + x);
}
};
复杂度分析
时间复杂度: O ( n + m ) O(n+m) O(n+m),其中 n n n 为数组 nums1
的长度, m m m 为数组 nums2
的长度。
空间复杂度: O ( 1 ) O(1) O(1),仅使用了几个额外的变量。
以上就是本篇文章的内容了,感谢您的阅读。
如果感到有所收获的话可以给博主点一个 哦。
如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出。