前情回顾:断了好多天的日记又开始复写,因为从4月13到4月16号晚上,都在疲于装系统的事情,搞得焦头烂额,但确实也收获了很多,学会了uefi引导与mbr引导,单硬盘与多硬盘的区别,下面的装机网址真的好,要常读常新。
https://www.cnblogs.com/masbay/articles/10745170.html?utm_source=wechat_session&utm_medium=social&utm_oi=843948068373143552
其中由于实验室电脑(实验室台式机电脑没有无线网卡)有线连接的问题,不知道是其ip地址不够的问题还是什么,其一直会出现网络断断续续的情况,不过好在解决了这个问题,是通过硬件解决的,重新加一个路由器,然后从路由器里连出网线插入到电脑上,有线连接就不会断。
今日正常:
- 回顾背包问题,在面对0-1背包的时候,状态满足条件下能转移的是否需要转移,这个是需要比较的,而不是直接让其转移,看最终谁更能符合我们的最终条件
// 装入或者不装入背包,择优
dp[i][w] = Math.max(
dp[i - 1][w - wt[i-1]] + val[i-1],
dp[i - 1][w]
- 背包问题引出的组合数与排列数问题
https://leetcode-cn.com/problems/coin-change-2/solution/ling-qian-dui-huan-iihe-pa-lou-ti-wen-ti-dao-di-yo/
这个总结对于组合数与排列数的总结非常的到位。
组合数/排列数的根本原因在于1,2与2,1是不是一种情况,即是否有序。对于二维dp的定义两者是相等的,但是对于状态空间压缩后的情况,两种情况不等。
总结如下:二维dp的组合数问题和排列数问题 都可以交换嵌套的循环,因为子问题不会变化; 一维的dp组合数问题和排列数问题 不可以交换嵌套的循环,因为会改变子问题; 一维的dp组合数问题,交换嵌套的循环,子问题会变成排列数问题; 一维的dp排列数问题,交换嵌套的循环,子问题会变成组合数问题;
①据题目所求可以确定是组合数问题还是排列数问题,就可以决定dp表的横纵坐标分别表示什么了,之后无论用二维dp还是一维dp,状态的横纵坐标都是不变的 ②二维一维其实是看你的dp数组是一维还是二维决定的 ③如果写成了一维,那么两层循环的顺序不能改变----------一维的循环顺序(只能一行一行求解)为什么不能改变呢?因为如果改变循环顺序的话,变成了一列一列求,当求到第一列最后一行时,第一列前几行的数据已经被覆盖,当求第二列时,得到的数据是错的 ④如果写成了二维,那么两层循环的熟悉怒可以改变--------循环的顺序改变其实改变的的是一列一列求还是一行一行求,所以顺序是可以改变的(因为二维数组可以保存每一列和每一行的数据,但是一维的dp只能保存一行一行的保存数据)
从这个问题里面可以衍生成许多不同的问题,零钱兑换问题的I,II,爬楼梯问题。
背包问题继续强化
https://leetcode-cn.com/problems/coin-change-2/solution/gong-shui-san-xie-xiang-jie-wan-quan-bei-6hxv/
3.leetcode4月16个人赛
第三题,染色体染色的题目
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int getNumber(TreeNode* root, vector<vector<int>>& ops) {
//鉴于二叉树中没有重复的值,可以额外设置标记
//定义hashmap
unordered_map<int,string>hp;
int n=ops.size();
for(int i=0;i<n;i++)
{
traverse(root,ops[i],hp);
}
int sum=0;
for (auto iter = hp.begin(); iter !=hp.end(); ++iter) {
if(iter->second=="red")
{
sum++;
}
}
return sum;
}
void traverse(TreeNode* root,vector<int>& a,unordered_map<int,string>&hp)
{
if(root==nullptr)
{
return;
}
if(root->val>=a[1]&&root->val<=a[2] && a[0]==0)
{
//0是蓝色
if(hp.count(root->val)==0)
{
hp[root->val]="blue";
}
else
{
if(hp[root->val]=="red")
{
hp[root->val]="blue";
}
}
}
if(root->val>=a[1]&&root->val<=a[2] && a[0]==1)
{
//1是红色
if(hp.count(root->val)==0)
{
hp[root->val]="red";
}
else
{
if(hp[root->val]=="blue")
{
hp[root->val]="red";
}
}
}
traverse(root->left,a,hp);
traverse(root->right,a,hp);
}
};
死在了时间复杂度上,其实是自己糊涂了吗,第一遍便利都把信息都存储在了哈希表中,第二遍还去遍历,真是个傻逼。
第二遍去写,好像自己采用了能减小时间复杂度的方法,其实没有,循环的次数是一样的
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int getNumber(TreeNode* root, vector<vector<int>>& ops) {
//鉴于二叉树中没有重复的值,可以额外设置标记
//定义hashmap
unordered_map<int,string>hp;
int n=ops.size();
traverse(root,hp);
for(int i=0;i<n;i++)
{
for (auto iter = hp.begin(); iter !=hp.end(); ++iter)
{
if(iter->first>=ops[i][1]&&iter->first<=ops[i][2] && ops[i][0]==0)
{
cout<<iter->second;
iter->second="blue";
}
if(iter->first>=ops[i][1]&&iter->first<=ops[i][2] && ops[i][0]==1)
{
iter->second="red";
}
}
}
int sum=0;
for (auto iter = hp.begin(); iter !=hp.end(); ++iter) {
if(iter->second=="red")
{
sum++;
}
}
return sum;
}
void traverse(TreeNode* root,unordered_map<int,string>&hp)
{
if(root==nullptr)
{
return;
}
hp[root->val]="chushi";
traverse(root->left,hp);
traverse(root->right,hp);
}
};
其实上面的时间复杂度仍然没有变化。时间复杂度为:树节点的个数乘上ops数组行的数目