有营养的算法笔记(一)
有营养的算法笔记
- 调整二叉树
- 猜数字大小
- 二进制中1的个数为target的数量
调整二叉树
1.题目描述
给定一棵多叉树的头节点head,每个节点只有黑白两色所有黑节点都保留,所有从头节点到黑节点路径上的点都保留返回处理后树的头节点
意思就差不多是上面这个图一样,保留黑色节点并将沿途路径上的节点都要保留。
2.解题思路
这个题了直接干就是了深度优先遍历,先遍历其孩子节点将其孩子节点处理完毕之后用一个容器保存好如果一个节点孩子节点被全部删除了,并且它自己也不是黑色节点那么这个节点给上层返回nullptr,否则这个更新这个节点的孩子节点并返回
3.对应代码
#include<iostream>
#include<vector>
using namespace std;
//给定一棵多叉树的头节点head,每个节点只有黑白两色
//所有黑节点都保留,所有从头节点到黑节点路径上的点都保留
//返回处理后树的头节点
struct TreeNode
{bool retain;//每个节点是否需要被保留也就是是黑色节点还是白色节点vector<TreeNode*>nexts;//邻居节点int val;TreeNode(int v,int r):val(v),retain(r){}};
typedef TreeNode Node;
Node* Reatin(Node* head)
{//没有子节点可以看自己是否是黑色节点if (head->nexts.empty()) {return head->retain ? head : nullptr;}vector<Node*>newNext;//遍历其孩子节点for (auto next : head->nexts) {Node* ret = Reatin(next);if (ret){newNext.push_back(ret);}}//如果他的孩子节点调整之后还有,或者当前节点需要保留if (!newNext.empty() || head->retain) {head->nexts = newNext;return head;}//否则直接返回空return nullptr;
}int main()
{return 0;
}
猜数字大小
1.对应OJ链接
猜数字大小
2.题目描述
3.解题思路
很明显这是一个范围上的尝试模型。我们可以设计一个这样的尝试,我们已经确定了答案就在这个1到n当中即为L到R当中。所以我门就可以设计这样的一个尝试。现在我已经确定了答案就在L…R当中请返回我最倒霉的情况下需要的最小金币数。下面我们来分析可能性:
可能性1:我就猜开头位置也就是L那么我最倒霉那么也就是我没有猜对承担了一个L的代价,那么在[L+1…R]范围上继续搞
可能性2:我就猜结尾位置也就是R位子,就算我最倒霉没猜中承担了一个R的代价,继续在[L…R-1]范围内继续搞
可能性3:这个可能性可就多了[L+1…R-1]范围内的数字我全试抓一个最好的答案更新最好的答案。
4.对应代码
class Solution {public:vector<vector<int>>dp;int getMoneyAmount(int n) {dp.resize(n+1,vector<int>(n+1,-1));return process(1,n);}//现在我已经锁定了答案一定就在[L....R]范围内返回我最倒霉的情况下需要的最小现金数int process(int L,int R){//只有一个数if(L==R){return 0;}//两个数我们肯定猜L就算我最倒霉那么我承担的代价也就算Lif(L==R-1){return L;}if(dp[L][R]!=-1){return dp[L][R];}int p1=process(L+1,R)+L;//我就猜Lint p2=process(L,R-1)+R;//就猜R//(L.....R)位置我全试int ans=min(p1,p2);for(int i=L+1;i<R;i++){int left=process(L,i-1);int right=process(i+1,R);int cur=max(left,right)+i;//我最倒霉ans=min(ans,cur);}dp[L][R]=ans;return ans;}
};
二进制中1的个数为target的数量
1.题目描述
限制:0 <= start <= end,0 <= target <= 64[start,end]范围上的数字,有多少数字二进制中1的个数等于target。
2.解题思路
最容易想到的就是遍历这个范围内的每一个数字,求每个数字当中二进制为1的数量如果数量等于target我们就累加答案。思路非常的简单,对于暴力解来说。下面我们先来看看暴力解是怎么写的
3.对应代码:
typedef long long ll;
//限制:0 <= start <= end,0 <= target <= 64
//[start, end]范围上的数字,有多少数字二进制中1的个数等于target
int BitOne(ll num)
{//获取某一个数字当中二进制当中1的个数int ans = 0;while (num){if (num % 2 == 1) {ans++;}num /= 2;}return ans;
}
ll GetNums1(ll start, ll end, int target)
{ll ans = 0;//一个一个开始尝试for (ll i = start; i <= end; i++) {if (BitOne(i) == target) {ans++;}}return ans;
}
下面我们来看看比较优良的方法,这种方法真的不是人能想的。首先我们想一个问题
1.如果我们能够求出[0…start]范围内二进制位当中个数等于target的数量有几个假设为a,我们也能求出[0…end]范围内二进制位当中个数等于target的数量假设为b,那么答案不就是b-a个吗
2.那么现在的关键就在于如何求[0…a]范围内二进制当中等于target的数量,现在我们可以这样进行尝试我们先把a二进制当中最高位为1的数量拿到。从这个比特位开始进行尝试,每个比特位的位置可以填1或者0但是所做的选择必须对应的数值必须小于a。于是我们就可以进行尝试:
num[h…index+1]决定完了,需要保证之前做的决定不能比num要大
可能性:
(1)之前做的决定已经小于num对应的状态了
(2)之前做的决定已经等于num对应的状态了index…去做决定吧
less1说明做的决定小于num所对应的状态,less0说明之前做的决定等于num所对应的前缀状态rest代表还剩下几个1,[0…index].[index…]有多少个决定并将不能超过num
下面让我们来看看代码:
#include<iostream>
using namespace std;
typedef long long ll;
//限制:0 <= start <= end,0 <= target <= 64
//[start, end]范围上的数字,有多少数字二进制中1的个数等于target
int BitOne(ll num)
{//获取某一个数字当中二进制当中1的个数int ans = 0;while (num){if (num % 2 == 1) {ans++;}num /= 2;}return ans;
}
ll GetNums1(ll start, ll end, int target)
{ll ans = 0;//一个一个开始尝试for (ll i = start; i <= end; i++) {if (BitOne(i) == target) {ans++;}}return ans;
}
//num[h...........index+1]决定完了,需要保证之前做的决定不能比num要大
/*可能性:(1)之前做的决定已经小于num对应的状态了(2)之前做的决定已经等于num对应的状态了index.............去做决定吧less==1说明做的决定小于num所对应的状态less==0说明之前做的决定等于num所对应的前缀状态rest代表还剩下几个1[0.........index][index.........]有多少个决定并将不能超过num
*/
ll process(int index, int rest, int less, int num)
{if (rest > index + 1) {return 0;}//搞定了找到了一种方案if (rest == 0) {return 1;}//小于numif (less == 1){if (index + 1 == rest) {return 1;}else{return process(index - 1, rest, less, num) + process(index - 1, rest - 1, less, num);}}else{if (index + 1 == rest) {return (num & (1 << index)) == 1 ? process(index - 1, rest - 1, less, num) : 0;}if ((num & (1 << index)) == 0) {return process(index - 1, rest, 0, num);}else//index位置为1{return process(index - 1, rest - 1, 0, num) + process(index - 1, rest, 1, num);}}}ll GetNums2(ll start, ll end, int target)
{if (start < 0 || end<0 || start>end || target < 0) {return 0;}if (start == 0 && end == 0) {return target == 0 ? 1 : 0;}int ehigh = 62;//寻找最高位为1的状态while ((end & (1LL << ehigh)) == 0) {ehigh--;}if (start == 0) {return process(ehigh, target, t, end);}else {start--;//为了方便做差int shigh = 62;while (shigh>=0&&(start&(1LL<<shigh))==0){shigh--;}return process(ehigh, target,0, end)- process(shigh, target,0, start);}
}int main()
{srand(time(0));int times = 1000;for (int i = 0; i < times; i++){int start = rand() % 100 + 1;int end = rand() % 1000 + 1;int target = rand() % 100 + 1;if (start <= end){int ans1 = GetNums1(start, end, target);int ans2 = GetNums2(start, end, target);if (ans1 != ans2) {cout << "错了" << endl;return 0;}}}cout << "对了" << endl;
}
有营养的算法笔记(一)相关推荐
- 【有营养的算法笔记】基础算法 —— 推导证明前缀和与差分
- 《算法笔记》中文版 - 包括数组,链表,树,图,递归,DP,有序表等相关数据结构与算法的讲解及代码实现...
来源:专知本文为资源,建议阅读5分钟本文为你分享<算法笔记>中文版. https://github.com/Dairongpeng/algorithm-note 目录概览 第一节 复杂度. ...
- 数据结构与算法笔记 - 绪论
数据结构与算法笔记 - 绪论 1. 什么是计算 2. 评判DSA优劣的参照(直尺) 3. 度量DSA性能的尺度(刻度) 4. DSA的性能度量的方法 5. DSA性能的设计及其优化 x1. 理论模型与 ...
- 数据结构与算法笔记(十六)—— 二叉搜索树
一.二叉搜索树定义 二叉搜索树(Binary Search Tree),又名二叉排序树(Binary Sort Tree). 二叉搜索树是具有有以下性质的二叉树: 若左子树不为空,则左子树上所有节点的 ...
- 数据结构与算法笔记(十五)—— 散列(哈希表)
一.前沿 1.1.直接寻址表 当关键字的全域U比较小时,直接寻址是一种简单而有效的技术.假设某应用要用到一个动态集合,其中每个元素都有一个取自全域U={0,1,-,m-1)的关键字,此处m是一个不很大 ...
- 《algorithm-note》算法笔记中文版正式发布!
无论是做机器学习.深度学习.自然语言处理还是其它领域,算法的重要性不言而喻!吃透算法底层原理.掌握算法数学推导和代码实现,对提高自己的硬核实力来说非常重要!今天给大家推荐一个超赞的开源算法笔记!中文版 ...
- 【算法】《algorithm-note》算法笔记中文版正式发布!
无论是做机器学习.深度学习.自然语言处理还是其它领域,算法的重要性不言而喻!吃透算法底层原理.掌握算法数学推导和代码实现,对提高自己的硬核实力来说非常重要!今天给大家推荐一个超赞的开源算法笔记!中文版 ...
- c++ string 删除字符_算法笔记|(5)第二章C、C++的快速入门字符数组的存放方式string.h文件...
字符数组的存放方式 由于字符数组是由若干个char类型的元素组成的,因此字符数组的每一位都是一个char字符,除此之外,在一维字符数组或者二维字符数组的第二维的末尾都有一个空字符\0表示存放的字符串的 ...
- 算法笔记(JavaScript版)——排序
算法笔记(JavaScript版)--排序 本文内容根据Rebert Sedgewick和Kevin Wayne的<算法(第四版)>整理,原代码为java语言,自己修改为JavaScrip ...
最新文章
- 【Linux】Linux简单操作之安装jdk
- AliCloudDB for redis应用场景之存储最新N条聊天记录
- Tomcat配置server.xml
- Ubuntu网络配置方法
- SQL提取时间段内数据
- Confluence 6 为发送邮件配置服务器
- 苹果7手机计算机怎么看历史记录,苹果手机safari书签及其历史记录怎么恢复
- 关于windows的version和OS build version
- 12 快件文档“更新终止”从作者“xxx”收到
- 阿里双11大促秒杀活动下的缓存技术与高水位限流实现
- java高端架构_Java高端架构师
- 给大家介绍一个日期输入控件javascript实现,我修改了下,符合我的习惯了,^_^!...
- PAT1023. 组个最小数
- mysql对所有id求积_MySQL学习笔记(二)—查询
- C# dataGridView控件 左上角加string
- 利用MFC和Opencv读取摄像头
- 基于html的明星网站
- 电总协议串口调试助手
- 一款开源免费的办公套件系统:DzzOffice详细部署
- 数据分析,把握商机 关键词采集工具助你挖掘潜在客户