其实说起来dp和hash是一种很好的解题思路,而且这两个方法再低阶算法里面是很受用的,而且也是相对来说简单一点的,当然了这个简单仅仅限于leetcode中等题并且不与树或者并查集或者高级数据结构一起考虑的情况下,单纯的去考hash和dp的话不是特别难,所以说这两个方法大家一定要多加练习之后掌握了对于我们普通的求职肯定是够用的了。
我对于dp和hash说一下我个人的看法:
目录
dp:
大家都知道dp 是动态规划,但是真正意义上了解的人又有几个呢?b站有个很火的讲算法的闫总,他著名的闫氏dp分析法,大家又有几个人能再真正做题的时候用到呢?我想这恐怕是难上加难得吧,所谓“授人以鱼不如授人以渔”,所以我今天可以把我每次做dp的思路给大家分享一下,当然了我也是从别的大牛那里学来的,所以如果有雷同,纯属意外,话不多说进入正题:
其实大家仔细想一下dp的出现打破了什么,再dp没有的时候我们大多数的时候都是进行dfs或者bfs深搜最多加上回溯来进行计算,我来举一个例子大家理解一下
给定一个三角形 triangle ,找出自顶向下的最小路径和。
每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标 i 或 i + 1 。
很多人再大学的时候取学习程序设计与算法的时候肯定学过dp,那么肯定就会见过这道题,很经典的题目,过去如果你没有学习dp的话,在之前你肯定是学习过递归了,一眼看过去这不是深度优先搜索吗,对,没错,就是深搜其实很多题用深搜的思路去理解都豁然开朗,但是这个题深搜得看题目给的数据量大不大,leetcode里面给的是200说实话这个数据量足以把栈给撑爆所以是不可取的,但是大家可以看看dfs来理解理解思路
void dfs(int sum,int i,int j,int** triangle, int triangleSize, int* triangleColSize,int* min)
{
if(i==triangleSize) //设置结束时间这是你做递归的基本素养
{
*min=fmin(*min,sum);
return;
}
int p;
for(int k=0;k<2;k++) //向下或者向右下走
{
p=j+k;
if(p<triangleColSize[i])
{
sum+=triangle[i][p];
i++;
dfs(sum,i,p,triangle,triangleSize,triangleColSize,min);
i--; //设置回溯条件
sum-=triangle[i][p];
p=j-k;
}
}
}
int minimumTotal(int** triangle, int triangleSize, int* triangleColSize){
int min=210;
dfs(0,0,0,triangle,triangleSize,triangleColSize,&min);
return min;
}
下面是对于上面dfs的思路讲解,就是一直搜索直到尽头为止,原来很简单,但是大家会发现代码冗余量太大了,所以肯定要改进,所以我们引出来了dp
dp[new][j]=fmin(dp[old][j],dp[old][j-1])+triangle[i][j];
主要就是在于这个方程,极大程度上的减少了代码计算的冗余量,因为我们不是向下就是向右下,所以我们就用数组来模拟这个过程即可,就得到了上面的这个方程,所谓的空间换时间
int minimumTotal(int** triangle, int triangleSize, int* triangleColSize){
int dp[2][triangleSize];
int i,j,old=1,new=0;
memset(dp,0,sizeof(dp));
dp[0][0]=triangle[0][0];
for(i=1;i<triangleSize;i++)
{
new=old;
old=1-new;
for(j=0;j<triangleColSize[i];j++)
{
if(j==0)
{
dp[new][j]=dp[old][j]+triangle[i][j];
continue;
}
if(j==triangleColSize[i]-1)
{
dp[new][j]=dp[old][j-1]+triangle[i][j];
continue;
}
dp[new][j]=fmin(dp[old][j],dp[old][j-1])+triangle[i][j];
}
}
int min=210;
for(j=0;j<triangleColSize[triangleSize-1];j++)
{
min=fmin(min,dp[new][j]);
}
return min;
}
hash:
其实对于hash就很简单了就是hash排序,就只是一个数组来存储一个hash值的过程,当我们需要使用的时候就把他提出来即可,大家可以看看代码,不懂得评论区或者私信问都可。
void sortColors(int* nums, int numsSize){
int i,j=0,k=0;
int hash[3];
memset(hash,0,sizeof(hash));
for(i=0;i<numsSize;i++)
{
hash[nums[i]]++;
}
for(i=0;i<3;i++)
{
k=0;
while(k<hash[i])
{
nums[j]=i;
j++;
k++;
}
}
}