常用5大算法思維
1. 动态规划简单介绍
推荐博文-漫画动态规划
动态规划中的三个重要的概念:
最优子结构
边界
状态转移公式
【例】爬楼梯问题,一次一步或者两步,
F(1) = 1;
F(2) = 2;
F(n) = F(n-1) + F(n-2) (n>=3);
1、F(n-1) 和 F(n-2)是F(n)的【最优子结构】
2、F(1)和F(2)可以直接得到结果,是问题的【边界】
3、F(n) = F(n-1)+F(n-2)是阶段和阶段之间的【状态转移方程】
问题:最长递增子序列
设置dp[i]是数组以i下标的数组段的最长递增子序列,最后的结果:
for(int i=0; i<arr.size(); i++)
{
res = max(res, dp[i]);
}
return res;
问题:dp[0...4]怎么推算出dp[5]
dp[5]是数组以5下标的数组段的**最长**递增子序列
i = 5;此处
for(int j=0; j<i; j++)
{
if(arr[i] > arr[j])
dp[i] = max(dp[i], dp[j]+1);
}
综合:
//初始化dp数组值
for(int i=0; i<arr.size(); i++)
{
for(int j=0; j<i; j++)
{
if(arr[i] > arr[j])
dp[i] = max(dp[i], dp[j]+1);
}
}
for(int i=0; i<arr.size(); i++)
{
res = max(res, dp[i]);
}
return res;
2. 分治算法
3. 貪心算法
贪心算法原理
每次选择局部最优化解,通常和其他算法结合使用
4. 回溯算法(搜索问题)
推荐博文
【定义】探索与回溯法,是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”
【使用场景】八皇后问题、背包问题
* result = []
* def backtrack(路径,选择列表):
* if 满足结束条件:
* result.add(路径)
* return
* for 选择 in 选择列表:
* 做选择
* backtrack(路径,选择列表)
* 撤销选择
*
void backtrack(std::vector<std::string> &res, std::string s, std::string &track, std::vector<bool> &visit) {
// 回溯结束条件
if(track.size() == s.size()){
res.push_back(track);
return;
}
// 选择和选择列表
for(int i = 0; i < s.size(); i++){
// 排除不合法的选择
if(visit[i]){
continue;
}
if(i > 0 && !visit[i-1] && s[i-1] == s[i]){
continue;
}
visit[i] = true;
// 做选择
track.push_back(s[i]);
// 进入下一次决策树
backtrack(res, s, track, visit);
// 撤销选择
track.pop_back();
visit[i] = false;
}
}
#include "stdio.h"
#include "stdbool.h"
#define SIZE 4
int queen[SIZE]={0};
bool is_ok(int row)
{
for(int j=0; j<row; j++)
{
if(queen[row]==queen[j] || row-queen[row]==j-queen[j] || row+queen[row]==j+queen[j])
return false;
}
return true;
}
void queen_postion(int row)
{
if(row >= SIZE)
{
//找到了符合要求的结果
for(int i=0; i<SIZE; i++)
{
printf("%d",queen[i]);
}
return;
}
for(int i=0; i<SIZE; i++)
{
// 记录下每一行的位置,若是is_ok为false,则会选择另一个解
queen[row] = i;
//判断前面所有选择的是否满足要求,有些需要借助status的信息表,并且回溯和更新status
if(is_ok(row))
{
queen_postion(row+1);
}
}
}
int main(int argc, char *argv[])
{
int row = 0;
queen_postion(row);
return 0;
}
void dfs(int i,int cv,int cw)
{ //cw当前包内物品重量,cv当前包内物品价值
if(i>n)
{
if(cv>bestval) //是否超过了最大价值
{
bestval=cv; //得到最大价值
for(i=1;i<=n;i++)
bestx[i]=x[i]; //得到选中的物品
}
}
else {
for(int j=0;j<=1;j++) //枚举物体i所有可能的路径,
{
x[i]=j;
if(cw+x[i]*w[i]<=TotCap) //满足约束,继续向子节点探索
{
cw+=w[i]*x[i];
cv+=val[i]*x[i];
dfs(i+1,cv,cw);
cw-=w[i]*x[i]; //回溯上一层物体的选择情况
cv-=val[i]*x[i];
}
}
}
}
5. 分支界限算法
排序算法
文章地址:8中常見的排序算法
查找算法
文章地址:各種常見查找算法
分类算法
文章地址:
海量数据处理算法
- bitmap和2-bitmap
bitmap使用大全有一个链接17道面試題
bitmap原理和查找數方法 - Top-K算法
top-k算法原理
C語言實現代码