2024-03-08 leetcode写题记录
2024-03-08 leetcode写题记录
27. 移除元素
题目链接
题意
给你一个数组\(nums\)和一个值\(val\),你需要原地移除所有数值等于\(val\)的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用\(O(1)\)额外空间并原地修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
解法
遍历一遍,把不等于\(val\)的值都\(swap\)到前面即可。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int n = nums.size(), idx = 0;
for (int i = 0; i < n; ++i) {
if (nums[i] == val)
continue;
swap(nums[idx], nums[i]);
idx++;
}
return idx;
}
};
179. 最大数
题目链接
题意
给定一组非负整数\(nums\),重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。
注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。
解法
用贪心的想法想一下,两个数的比较其实就是在比哪个数在前时能让整个数变得更大。
注意,\(f()\)会爆\(int\)。
class Solution {
public:
int f(int x) {
long long res = 10;
while(x >= res) res *= 10;
return res;
}
string largestNumber(vector<int>& nums) {
sort(nums.begin(), nums.end(), [&](int& x, int& y) {
int xx = f(x), yy = f(y);
return 1ll * x * yy + y > 1ll * y * xx + x;
});
if (nums[0] == 0) return "0";
string res = "";
for (int x : nums)
res += to_string(x);
return res;
}
};
75. 颜色分类
题目链接
题意
给定一个包含红色、白色和蓝色、共\(n\)个元素的数组\(nums\),原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数\(0、1\)和\(2\)分别表示红色、白色和蓝色。
必须在不使用库内置的\(sort\)函数的情况下解决这个问题。
解法
遍历一遍,是\(0\)就扔左边,是\(2\)就扔右边,处理好边界就行了。
class Solution {
public:
void sortColors(vector<int>& nums) {
int n = nums.size(), l = 0, r = n - 1;
for (int i = l; i <= r; ++i) {
if (nums[i] == 0)
swap(nums[l++], nums[i--]);
else if (nums[i] == 2)
swap(nums[r--], nums[i--]);
if (i < l - 1) i = l - 1;
}
}
};
215. 数组中的第K个最大元素
先吐槽,这题真垃圾。题目上写着让想时间复杂度\(O(n)\)的算法,但是官方题解说的什么玩意都是,时间复杂度还不写最坏时间复杂度,测试数据又卡的离谱,怪不得讨论区一堆骂的,给我卡麻了。这题想\(O(nlogn)\)的就行。
题目链接
题意
给定整数数组\(nums\)和整数\(k\),请返回数组中第\(k\)个最大的元素。
请注意,你需要找的是数组排序后的第\(k\)个最大的元素,而不是第\(k\)个不同的元素。
解法
快速排序
快排的\(partition\)不稳定,这个题也没能过完所有样例,所以一般也不用。这里之所以写是为了回顾下快排写法,防止面试卡住。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int n = nums.size(), l = 0, r = n - 1, now = -1, des = n - k;
while (now != des) {
if (now < des)
now = partition(nums, now + 1, r);
else
now = partition(nums, l, now - 1);
}
return nums[now];
}
int partition(vector<int>& a, int begin, int end) {
int l = begin, r = end;
while (l < r) {
while (l < end && a[l] <= a[begin])
l++;
while (begin < r && a[r] >= a[begin])
r--;
if (l < r)
swap(a[l], a[r]);
}
swap(a[begin], a[r]);
return r;
}
};
二分
正负数都有的二分,注意边界判断。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int l = -10005, r = 10005;
while(l < r) {
int mid = (l + r) / 2 + 1, sum = 0;
if (l + r < 0) mid--;
for (int x : nums)
if (x >= mid) sum += 1;
if (sum < k)
r = mid - 1;
else
l = mid;
}
return l;
}
};
大根堆
手敲下大根堆。
写堆只要注意写好\(heapify()\)就行,其他的操作都是由这转化过去的。
class Solution {
public:
void heapify(vector<int>& a, int idx) {
if (idx < 0) return;
int n = a.size();
if (idx >= n) return;
int l = 2 * idx + 1, r = 2 * idx + 2;
if (l >= n) return;
if (r == n) {
if (a[idx] < a[l]) swap(a[idx], a[l]);
return;
}
if (a[idx] >= a[l] && a[idx] >= a[r]) return;
int next_idx = (a[l] > a[idx] && a[l] >= a[r]) ? l : r;
swap(a[idx], a[next_idx]);
heapify(a, next_idx);
}
void build(vector<int>& a) {
int n = a.size();
for (int i = n / 2 - 1; i >= 0; --i) heapify(a, i);
}
void del(vector<int>& a) {
a[0] = -100000;
heapify(a, 0);
}
int findKthLargest(vector<int>& nums, int k) {
build(nums);
for (int i = 0; i < k - 1; ++i) del(nums);
return nums[0];
}
};