- 上周有些事情回了趟老家,祝广大博友身体健康,多运动。
- 前面的贪心算法题目后面慢慢补,近期找到了一个实习,大概持续三个月,现在计划是白天工作,晚上下班以后运动运动+刷题。
- 要加强牛客网那种两小时3道题的刷题方式,限时刷题,贴近实际机考。
第一题 01背包问题
卡尔网题目链接:https://kamacoder.com/problempage.php?pid=1046
题解
#include <iostream>
#include <vector>
using namespace std;
// 0-1 bag 2D array solution
int bag_01_2DArray()
{
int m, bagWeight;
cin >> m >> bagWeight;
vector<int> weight(m), value(m);
for (int i = 0; i < m; i++)
cin >> weight[i];
for (int i = 0; i < m; i++)
cin >> value[i];
// initialize
// vector<vector<int>> dp(m, vector<int>(bagWeight + 1, 0));
vector<int> dp(bagWeight + 1, 0);
for (int i = 0; i < m; i++)
{
// when j < weight[i], we do not change the value , so the loop ends
for (int j = bagWeight; j >= weight[i]; j--)
{
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
}
}
cout << dp[bagWeight] << endl;
return 0;
}
// 0-1 bag roll array solution
int bag_01_rollArray()
{
int m, bagWeight;
cin >> m >> bagWeight;
vector<int> weight(m), value(m);
for (int i = 0; i < m; i++)
cin >> weight[i];
for (int i = 0; i < m; i++)
cin >> value[i];
// initialize
vector<vector<int>> dp(m, vector<int>(bagWeight + 1, 0));
for (int j = weight[0]; j <= bagWeight; j++)
dp[0][j] = value[0];
for (int i = 1; i < m; i++)
{
for (int j = bagWeight; j >= 0; j--)
{
if (j < weight[i])
dp[i][j] = dp[i - 1][j];
else
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
}
}
cout << dp[m - 1][bagWeight] << endl;
return 0;
}
int main()
{
bag_01_rollArray();
return 0;
}
第二题:Leetcode416. 分割等和子集
题目描述
解题思路
这个题目可以转换为01背包问题:背包大小为数组和的一半,每份材料的weight和value就是nums元素取值。请问这种情况下,dp[二分之一sum] 是否等于 二分之一sum,如果等于,那么就存在,都则就不存在。
题解
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = accumulate(nums.begin(), nums.end(), 0);
if (sum & 1)
return false;
const int target = sum >> 1;
vector<int> dp(target + 1, 0);
for (int i = 0; i < nums.size(); i++) {
for (int j = target; j >= nums[i]; j--)
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
}
return dp[target] == target;
}
};
第三题:Leetcode238. 除自身以外数组的乘积
题目描述
解题思路
可以使用两个辅助数组,分别记录从左到右的乘积和从右到左的乘积,然后使用前缀积即可。
进一步,可以优化得到空间复杂度为O(1)的方案。
题解
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
if (nums.empty())
return {};
const int len = nums.size();
vector<int> ans(len, 1);
for (int i = 1; i < len; i++) {
ans[i] = ans[i - 1] * nums[i - 1];
}
int tmp = 1;
for (int i = len - 2; i >= 0; i--) {
tmp *= nums[i + 1];
ans[i] *= tmp;
}
return ans;
}
};
快排细节梳理
详见第一层 while循环后面的注释
写示例需要考虑多种情况,逆序、重复元素等等。
#include <iostream>
#include <vector>
using namespace std;
void quicksort(vector<int> &nums, const int left, const int right)
{
if (left >= right)
return;
int base = nums[left];
int l = left, r = right;
while (l < r)
{
// 这里和下面,一定有一个地方要带上等于号
// 物理意义是:base左边都小于 base值,右边都大于等于base值
while (l < r && nums[r] >= base)
r--;
nums[l] = nums[r];
while (l < r && nums[l] < base)
l++;
nums[r] = nums[l];
}
nums[l] = base;
quicksort(nums, left, l - 1);
quicksort(nums, l + 1, right);
}
int main()
{
// char str[3];
// std::cin>>str;
std::cout << "hello world" << std::endl;
vector<int> a{6, 5, 5, 4, 3, 3, 2, 1, -1, 10};
quicksort(a, 0, a.size() - 1);
for (auto n : a)
cout << n << " ";
cout << endl;
std::cout << "hello world" << std::endl;
return 0;
}