(参考数据结构与算法分析c++版本)
一、算法分析
(一)运行时间分析
1.简单的例子-最大子序列求和问题
给出一列数,找到哪个顺序序列最大。
正常自己想最简单的思路就是两个for,复杂度O(N2)
书上给了一种算法,分治最大子序列,肯定就出现三种情况
先找出前半部分最大的序列A1,再找出后半部分最大的序列A2,在找出包含前半部分包含最后一个元素的temp1A3,找出包含后半部分包含第一个一个元素的temp2A3,加和A3
三者最大的就是要求的,求解用二分迭代(但是2的幂时比较好解)复杂度O(NlogN),
最后书上给了O(N)的算法
int MaxSubSum4(const vector<> &a )
{
int ThisSum = 0;
int MaxSum = 0;
for(int j=0;j<a.size();j++)
{
ThisSum+=a[j];
if(ThisSum>MaxSum)
MaxSum=ThisSum;
elseif(ThisSum<0)
ThisSum=0;
}
return MaxSum;
}
具体解释参考这篇博客
https://blog.youkuaiyun.com/carl95271/article/details/79316190
其实想也好像,明白这句ThisSum=0; 就ok了。
二、算法设计技巧
( 一)、贪心算法
leedcode 135 candy
int candy(vector<int>& ratings) {
vector<int>count(ratings.size(),1);
int sum = 0;
for(int i = 0; i<ratings.size()-1; i++ )
{
if(ratings[i+1] > ratings[i])
{
count[i+1] = count[i] + 1;
}
}
for(int i = ratings.size()-1;i > 0;i--)
{
if(ratings[i-1] > ratings[i])
{
// count[i-1] = count[i]+1; 万一更小了呢
count[i-1] = max((count[i]+1),count[i-1]);
}
}
// for(int i = 0; i < count.size() ; i++) //更好的函数
// {
// sum += count[i];
// }
return sum = accumulate(count.begin(),count.end(),0);
注意两个问题:(1)贪心问题这里想的是左一遍,再右一遍,但是一定注意两者规则别冲突。
(2)学到了用accumulate函数做累计和,要不又是一遍for
( 二)双指针算法
(1)减少一遍遍历
(2)想问题时变得简单
(三)排序算法
这里就简单列出几种方法,有具体的说十大排序算法具体再看
1.快速排序(nlogn)
快速排序的原理解释
2.归并排序(nlogn)
描述原理及解释
3.插入排序(nn)
添加链接描述
冒泡排序(nn),选择排序(nn)
4.桶排序
(四)搜索算法
以后理解深了再来补充。
深度优先搜索
广度优先搜索
回溯法
(五)动态规划问题
大概思想:动态规划问题本质上首先是一种搜索算法,只不过它记录每步的值保存下来。而且要解决动态规划问题最重要的一个想法就是要找到当前点与前几步的关系(状态转移方程!!!)
(1)一维动态规划 :例如 走台阶只能一步两步,最少需要多少步骤阿。
(2)二维动态规划 :例如:一个二维矩阵,从头走到为最小的路径和啊。
(3)分割类问题 : 这也是一种动态规划问题,只不过他的状态转移矩阵不是相对而是依赖于满足分割条件的位置。
e.g:给定一个正整数,求其最少可以由几个完全平方数相加构成
(4)分割类问题:当然动态规划问题不会很多都这么明显的给你状态方程,有的会稍微变一下型
e.g :给定一个字符串和一个字符串集合,求是否存在一种分割方式,使得原字符串分割后的子字
符串都可以在集合内找到
这题还是有点不明白。
(5)子序列问题:
e.g :输入是一个一维数组,输出是一个正整数,表示最长递增子序列的长度。
e. g : 给定两个字符串,求它们最长的公共子序列长度。
输入输出样例
输入是两个字符串,输出是一个整数,表示它们满足题目条件的长度。
Input: text1 = “abcde”, text2 = “ace”
Output: 3
为什么你就是找不到其中的关系呢??????????
(6)背包问题
三、数据结构
(一)表
1 . 链表