【leetcode】划分为相等子集
题目地址
知识点:回溯法,深度搜索
解题思路:一个k大小的数组,k是要划分的子集个数。每一个元素可以任意放在让任何个位置,深度搜索+回溯可以遍历所有可能情况
class Solution {
public boolean canPartitionKSubsets(int[] nums, int k) {
int sum = 0;
for (int i = 0; i < nums.length; i++)
sum += nums[i];
if (sum % k != 0)
return false;
return helper(nums, new int[k], sum / k, nums.length-1);
}
public boolean helper(int[] nums, int[] sums, int target, int left)
{
if (left < 0)
return true;
int num = nums[left--];
for (int i = 0; i < sums.length; i++)
{//循环k数组每一个位置,将当前元素放进这个位置
if (sums[i] + num <= target)
{//如果这个位置可以放下当前元素
sums[i] += num;//累加
if (helper(nums, sums, target, left))
return true;//剪枝
sums[i] -= num;//回溯
}
if (sums[i] == 0)
return false;
}
return false;
}
}
最小代价爬楼梯
题目地址
知识点:动态规划
解题思路:题目叙述不明,按照测试用例,题目的意思是,从一阶楼梯可以网上跳一层或者两层,但是花费都是cost[i],可以从第0级或者第一级开始跳,也就是dp[0], dp[1]被初始化为0
#include <bits/stdc++.h>
using namespace std;
vector<int> split(string str)
{
int tmp = 0;
vector<int> res;
for (int i = 0; i < str.size(); i++)
{
if (str[i] >= '0' && str[i] <= '9')
tmp = tmp * 10 + (str[i] - '0');
else
{
res.push_back(tmp);
//cout << tmp << endl;
tmp = 0;
}
}
res.push_back(tmp);
return res;
}
int main()
{
string str;
cin >> str;
vector<int> costs = split(str);
vector<int> dp(costs.size() + 1, 0);
dp[0] = 0;
dp[1] = 0;
for (int i = 2; i <= costs.size(); i++)
{
dp[i] = std::min(dp[i-1] + costs[i-1], dp[i-2] + costs[i-2]);
//cout << dp[i] << endl;
}
cout << dp[dp.size()-1] << endl;
}
鸡鸭分类问题
题目地址
知识点:merge sort,交换次数
解题思路:
- 一个无序序列的最小交换次数可以使用merge sort来计算出来,在merge阶段记录right序列小于left序列的个数,累加即可得到最终交换次数
- 本题限制只有鸡鸭,那么可以简化为累加某一类前面与其不同的类的个数,即是交换次数
#include <bits/stdc++.h>
using namespace std;
int solve(vector<char>& chars, char pattern)
{
int cnt = 0, swap = 0;
for (int i = 0; i < chars.size(); i++)
{
if (chars[i] == pattern)
{
swap += (i - cnt);
cnt++;
}
}
return swap;
}
int main()
{
vector<char> chars;
char c;
while(cin >> c)
chars.push_back(c);
cout << min(solve(chars, 'C'), solve(chars, 'D')) << endl;
}
比特币最佳买卖时期
题目地址
知识点:最小值
解题思路:线性扫描,记录下当前位置之前的最小值,求差并于结果比较,记录最大值
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int> nums;
int num;
while(cin >> num)
nums.push_back(num);
int small = nums[0];
int res = 0;
for (int i = 1; i < nums.size(); i++)
{
res = max(res, nums[i] - small);
if (nums[i] < small)
small = nums[i];
}
cout << res << endl;
}
猫粮吃法
题目地址
知识点:二分法搜索
解题思路:二分法搜索,吃的速度最小值是SUM / H,最大值是猫粮最大堆的数量,二分搜索。我的解法简化了,直接累加
#include <bits/stdc++.h>
using namespace std;
int helper(vector<int>& nums, int k)
{
int res = 0;
for (int num: nums)
{
if (num % k == 0)
res += (num / k);
else
res += (num / k + 1);
}
return res;
}
int main()
{
vector<int> nums;
int num;
int sum = 0;
while(cin >> num)
{
nums.push_back(num);
sum += num;
}
int H = nums[nums.size()-1];
nums.pop_back();
sum -= H;
int K = sum / H;
while(helper(nums, K) > H)
K++;
cout << K << endl;;
}
括号配对问题
题目地址
知识点:栈
解题思路:遇到左括号加入栈,遇到右括号与栈顶元素比较,如果栈为空或者栈顶元素不是相应的左括号,返回错误
#include <bits/stdc++.h>
using namespace std;
int main()
{
string str;
cin >> str;
vector<char> sq;
for (int i = 0; i < str.size(); i++)
{
if (str[i] == '[' || str[i] == '(')
sq.push_back(str[i]);
else if (str[i] == ']')
{
if (sq.size() < 1 || sq[sq.size()-1] != '[')
{cout << "false" << endl; return 0;}
sq.pop_back();
}
else if (str[i] == ')')
{
if (sq.size() < 1 || sq[sq.size()-1] != '(')
{cout << "false" << endl; return 0;}
sq.pop_back();
}
}
string res = sq.size() == 0? "true": "false";
cout << res << endl;
}