数据结构与算法

参考《代码随想录》《hello, 算法》学习笔记

ACM模式处理:

1. 处理字符串输入

cin: 通过空白(空格、制表符、换行符)来确定字符串的结束位置,即cin在获取字符数组输入时只读取一个单词

getline():读取一整行,通过回车键输入的换行符来确定输入结尾,或者cin.getline().

        cin.getline(name, size)  读取19个字符或者遇到换行符停止读取

        getline(cin, str):读取输入的一行字符串

get():与getline()类似,但是会将换行符留在队列中,第二次调用get()时遇到这个保留的换行符认为输入到达末尾。处理这个换行符可以加一句没有参数的get()

  • 以逗号分隔字符串
  • 如string="asm,asd,grb",处理后得到 res[3]={asm, asd, grb};
vector<string> get_str(string &s){
    vector<string>res;
    string t;
    for(int i=0;i<s.size();i++){
        if(s[i]==','){
            res.push_back(t);
            t.clear();
        }
        else{
            t.push_back(s[i]);
        }
    }
    res.push_back(t);//最后一个字符没有逗号,手动加入
    return res;
}

  • 以空格分隔字符串

        istringstream()

string str = "this is a test";
istringstream iss(str);
string word;
vector<string> words;

while (iss >> word) {
words.push_back(word);
}

通用方法分割字符串(以单个字符分割)

    string origin_str = "hello world !"; // 需要进行分割的字符串
    //或者可以输入
    //string origin_str;
    //cin >> origin_str;

    stringstream ss(origin_str);         // 使用字符串构造一个stringstream类型(流)数据
    char c = ' '; // 设定好分隔符号(只能使用一个字符进行分割)
    vector<string> results; // 用来存储结果
    string str; //用来接收每个分割的字符串
    // 开始分隔
    while (getline(ss, str, c)) {
        results.push_back(str);
    }

1、数据结构:

1.数组

总结图:

内存分配

字节对齐

2.二叉树

  • 二叉平衡树:任意一个节点的左子树和右子树高度之差小于等于1
  • 完全二叉树:除了叶子节点这一层,每个节点都有两个子节点,且最后一层的节点靠左排列
  • 二叉搜索树:节点左边的节点值比该节点值小,右边节点值比该节点值大,中序遍历有序
  • 平衡二叉搜索树:二叉搜索树和平衡二叉树的结合

对于构建二叉树,必须存在中序遍历(有中序遍历才能分隔左右子树)

根据前序遍历和中序遍历构建二叉树

2、算法

1.回溯算法:

优点:本质上是DFS,能够找到所有可能的解决方案,在合理剪枝操作下,效率可以达到很高

局限性:不适用于大规模或者复杂问题,时间复杂度和空间复杂度很高

优化:1.剪枝,避免搜索不必要的路径  2.启发式搜索,引入估计值,优先搜索最可能的有效路径

代码框架:

void backtrack(   ){
 //1.判断是否有解
    if(issolution){
        record();//有解记录
        //找到解不继续搜索
        return;
    }
    //没找到解,遍历所有选择求解
    for(   ){
    //剪枝,并判断路径是否合法
        if(  ){
        //更新状态
        makechoice();
        //递归
        backtrack();
        ///回退
        undochoice();
    
        }
    
    }

}
应用:
1、全排列

给定数组,算出数组所有排列方式

  • 无相等元素

        所有元素是被唯一选择,可以用vector<bool>states标记每个元素的状态

        时间复杂度:O(n!)

  • 有相等元素

        在同一轮选择中,相等的元素可以重复选择,但是在下一轮中不能再选择相等的元素

        剪枝操作:如果choice[i]==choice[i-1],则跳过这次选择

2、子集和

给定数组,找出所有的集合(集合中元素之和为target),元素可以重复选择

  • 无重复元素

        由于元素可以重复选取,不适合用bool数组来标记状态,但需要对重复子集剪枝,如集合{4,5}和集合{5,4}

        剪枝操作:当前选择为s[i],下一轮选择从i开始往后选择

  • 有相等元素

        给定数组,找出所有的组合,使得组合元素之和为target,可能包含重复元素,每个元素只能选择一次

        只选择一次时需要标记元素选择情况:bool数组

        剪枝操作:避免在同一轮选择中选择相等的元素,先将数组排序,使得相等的元素相邻

        要点一:s[i]==s[i-1]时跳过本次选择

        要点二:下一轮选择,从i+1开始

        

3、N皇后

        给定n个皇后和一个nxn大小的棋盘,皇后可以攻击同一行、同一列以及同一斜线方向的棋子,要求两两皇后不能相互攻击

题解:逐行放置(在回溯函数中行参数为row+1即可)皇后,对列和对角线进行约束,记录每一列以及对角线是否有皇后

要点:同一主对角线:row-col 为恒定值,同一次对角线: row+col 为恒定值

注意:row-col 取值范围为 [-n+1, n-1]    row+col取值范围为[0-2n-2],因此对于标记主对角线的布尔数组diag1索引会出现负数,统一加上n-1

2. 动态规划

记忆化搜索:从顶至底,从原问题开始,将大问题分解为小问题,并采取数组记录重复子问题,因此常用递归来实现。

动态规划:从底至于顶,从小问题开始,构建大问题的解,因此使用循环迭代实现

动态规划解题关键:寻找递推公式,即状态转移方程

无后效性:给定一个确定的状态,他的未来发展只与当前的状态有关,而与过去经历的所有状态无关

应用:最优化问题
1. 最优子结构

原问题的最优解是从子问题的最优解构建得来的

第n阶最大方案数量等于第n-1阶和第n-2阶最大方案数量之和

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

alwaysonlinee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值