1. 数组能形成多少数对
难度
- Easy
- Medium
- Hard
完成情况
- 独立完成
- 参考思路
- 参考答案
思路
一开始用无序map,结果才超过5%,然后看数据范围,长度和数字都在100以下,那用map确实大材小用且浪费了。直接用一个101容量的数组即可。这次几乎双百了。
代码
class Solution {
public:
vector<int> numberOfPairs(vector<int>& nums) {
vector<int> ans(2, 0);
// unordered_map<int, int> ump;
// for (auto& num : nums) {
// ump[num]++;
// if (ump[num] == 2) {
// ump.erase(num);
// ++ans[0];
// }
// }
// ans[1] = ump.size();
vector<int> cnt(101, 0);
for (auto& num : nums) {
++cnt[num];
if ((cnt[num] & 1) == 0) ++ans[0];
}
ans[1] = nums.size() - (ans[0] << 1);
return ans;
}
};
2. 数位和相等数对的最大和
难度
- Easy
- Medium
- Hard
完成情况
- 独立完成
- 参考思路
- 参考答案
思路
原本的思路也没什么问题,主要是在找最大和的时候效率有些低。如果一个个去对比,要n的平方,而如果直接把相同数位和的数字排下序再计算和,就只要n的对数复杂度,以后应该注意这点。
代码
class Solution {
public:
int maximumSum(vector<int>& nums) {
auto bitSum = [&](int num) -> int {
int x = num;
int sum = 0;
while (x) {
sum += x % 10;
x /= 10;
}
return sum;
};
int n = nums.size();
unordered_map<int, vector<int>> ump;
vector<int> bitSums(n);
for (int i = 0; i < n; ++i) {
bitSums[i] = bitSum(nums[i]);
}
int ans = -1;
for (int i = 0; i < n; ++i) {
ump[bitSums[i]].push_back(nums[i]);
}
for (auto& elem : ump) {
int m = elem.second.size();
if (m == 1) continue;
sort(elem.second.begin(),elem.second.end());
ans = max(ans, elem.second[m - 1] + elem.second[m - 2]);
}
return ans;
}
};
3. 裁剪数字后查询第 K 小的数字
难度
- Easy
- Medium
- Hard
完成情况
- 独立完成
- 参考思路
- 参考答案
思路
参考这篇
直接根据题目描述进行模拟。
实现时并不用真的去截取字符串,或者将字符串转换为数字进行比较。遍历查询数组,定义一个sort的cmp,传入两个整数下标,根据下标指示的字符串和当前查询需要截取的位数,返回bool,用这种方式,将下标进行了排序,最后将排序后的下标返回即可。
按照同样的思路和逻辑写了一遍,结果有用例超时。仔细对比,发现是第二个字符串忘了写引用。一个符号引发的惨案。
代码
class Solution {
public:
vector<int> smallestTrimmedNumbers(vector<string> &nums, vector<vector<int>> &queries) {
vector<int> ans(queries.size());
int n = nums.size(), m = nums[0].length();
int index[n];
for (int i = 0; i < queries.size(); ++i) {
iota(index, index + n, 0);
auto& qur = queries[i];
stable_sort(index, index + n, [&] (int a, int b) -> bool {
auto& s = nums[a], &t = nums[b]; // 一定要用引用
for (int j = m - qur[1]; j < m; ++j) {
if (s[j] != t[j]) return s[j] < t[j];
}
return false;
});
ans[i] = index[qur[0] - 1];
}
return ans;
}
};
4. 使数组可以被整除的最少删除次数
难度
- Easy
- Medium
- Hard
完成情况
- 独立完成
- 参考思路
- 参考答案
思路
还是比较简单的,先求出第二个数组的最大公因数,再将第一个数组排序,遍历看当前元素是否能被最大公因数整除,不能就++ans。最后如果ans等于数组长度,则返回-1。
代码
class Solution {
private:
int gcd (int a, int b) {
if (a < b) {
a ^= b;
b ^= a;
a ^= b;
}
if (b == 0) return a;
else return gcd(b, a % b);
}
public:
int minOperations(vector<int>& nums, vector<int>& numsDivide) {
int maxFac = numsDivide[0];
for (int i = 1; i < numsDivide.size(); ++i) maxFac = gcd(maxFac, numsDivide[i]);
sort(nums.begin(), nums.end());
int j = 0;
int ans = 0;
for (; j < nums.size(); ++j) {
if (maxFac % nums[j] == 0) break;
else ++ans;
}
return ans == nums.size() ? -1 : ans;
}
};
5. 装满杯子需要的最短总时长
难度
- Easy
- Medium
- Hard
完成情况
- 独立完成
- 参考思路
- 参考答案
思路
每次取数组中最大的两个减一。
代码
class Solution {
public:
int fillCups(vector<int>& amount) {
int ans = 0;
sort(amount.begin(), amount.end());
while (amount[2] != 0) {
amount[2]--;
amount[1]--;
sort(amount.begin(), amount.end());
++ans;
}
return ans;
}
};
6. 无限集中的最小数字
难度
- Easy
- Medium
- Hard
完成情况
- 独立完成
- 参考思路
- 参考答案
思路
用set做存储。末尾是连续区间的最小值,前面是离散值。初始时只有一个1。删除时,先记录下set首元素,如果set大小为1,说明全部值都连续,那么在末尾插入一个加1值,然后抹去首元素。如果大于1,直接抹去即可。插入时,先看值是否在连续区间内(即是否大于set末尾元素),如果在,那么不用插入,如果不在,说明是离散值,直接插入即可(set自动去重)。
代码
class SmallestInfiniteSet {
private:
set<int> before;
public:
SmallestInfiniteSet() {
before.clear();
before.emplace(1);
}
int popSmallest() {
int x = *before.begin();
if (before.size() == 1) before.emplace(x + 1);
before.erase(before.begin());
return x;
}
void addBack(int num) {
if (num < *before.rbegin()) before.emplace(num);
}
};
7. 移动片段得到字符串
难度
- Easy
- Medium
- Hard
完成情况
- 独立完成
- 参考思路
- 参考答案
思路
首先认识到,如果两个字符串都删掉下划线后不相等,则前者一定无法变为后者(其实就意味着LR不能互相越过)。
其次,如果变化后的L在变化前L的右边,或者变化后R在变化前R的左边,也返回false。
代码
class Solution {
public:
bool canChange(string start, string target) {
auto s = start, t = target;
s.erase(remove(s.begin(), s.end(), '_'), s.end());
t.erase(remove(t.begin(), t.end(), '_'), t.end());
if (s != t) return false;
for (int i = 0, j = 0; i < start.size(); ++i) {
if (start[i] == '_') continue;
while (target[j] == '_') ++j;
if (i != j && (start[i] == 'L') == (i < j)) return false;
++j;
}
return true;
}
};
8. 统计理想数组的数目
难度
- Easy
- Medium
- Hard
完成情况
- 独立完成
- 参考思路
- 参考答案
思路
纯数学题……
代码
Comments NOTHING