MiaoRain / Algorithm_leetcode

0 stars 1 forks source link

递归 #4

Open MiaoRain opened 4 years ago

MiaoRain commented 4 years ago

大神笔记 https://github.com/algorithm006-class01/algorithm006-class01/issues/224#issue-566279035

哈希map和set map和set都分成两种,一种是有顺序,一种没有顺序。

对于有序map,内部元素通过key进行排序(a specific strict weak ordering criterion). 内部实现,二叉搜索树

对于无�序map(unordered_map),访问速度快于有序map. 内部元素根据他们的哈希值组织成buckets(桶),可以直接根据key进行访问。

map容器重载了操作符[]和=, 使得键值对的设置更加符合直觉,也更加方便。

set和map类似,只不过只存放key,不存放value。

调用例子

std::unordered_map<string, string> hash_table; //定义 hash_table["张三"] = "年轻司机"; //设置key-value hash_table["李四"] = "老司机"; //设置key-value hash_table["张三"] ; //访问已有的结果 hash_table["王五"] ; //访问不存在的元素,会新建一个元素,内容为空 hash_table.count("张三"); //计数key hash_table.find("张三") ;// 查找,如果找不到则返回hash_table.end() 242:有效的字母异位词 注意审题,例如这道题目

什么异位词 是否大小写敏感 可能的解题方法

暴力求解1,排序,判断是否相同 暴力求解2,哈希表,比较每个字母出现频次 类似的题目:49题

1:两数之和 最大误区: 题目只做一遍

好习惯: 收藏比较好的代码,整理成代码库

树 树的结构用于满足人类需求,例如递归树,状态树,决策树

二叉树的遍历,前序,中序,后序,相对于根的位置

树的循环比较麻烦,递归是更好的实现。

二叉搜索树,空树也是

左子树的所有节点都小于根 右子树的所有节点都大于根 依次类推,也就是重复性来源 二叉搜索树 Demo,https://visualgo.net/zh/bst

常见操作

查询: O(log n) 插入: O(log n) 删除: O(log n): 如果是叶子节点,直接删除,如果不是,则找第一个大于待删除节点来替换掉要删除的节点。 最差的情况,退换成单链表

必须记住的代码

def preOrder(self, root): if root: self.traverse_path.append(root.val) self.preOrder(root.left) self.preOrder(root.right)

def inOrder(self, root): if root: self.inOrder(root.left) self.traverse_path(root.val) self.inOrder(root.right)

def postOrder(self, root): if root: self.postOrder(root.left) self.postOrder(root.right) self.traverse_path(root.val) 题目 一个误区: 递归本身不存在效率低,效率差的问题,只要你的程序本身没有写残。递归相对于非递归,就在于递归需要额外开栈,因此在深度非常高的情况下,可能会差一些。但是目前编译器存在尾递归优化,可以认为递归和循环一样的效率。

题目用遍历做都不难,只要理解中序,前序,和后续的含义,也就是前中后是相对于根节点。

递归 递归本质就是循环,通过函数体来循环。

根本原因是 汇编没有循环嵌套一说, 比较常见的情况,就是不断跳到之前写的函数命令,循环汇编之后会递归其实差不多。

一层一层下降落,然后一层一层回来

函数参数和全局参数会在递归过程中会发生变化

代码模版

public void recur(int level, int param) {

// terminator if (level > MAX_LEVEL) { // process result return; }

// process current logic process(level, param);

// drill down recur( level: level + 1, newParam);

// restore current status 核心部分

终止条件 当前层逻辑 下探下一层 (可选)清理当前环境 思维要点:

不要人肉递归, 不要尝试绘制递归树 找到最近最简的方法,将其拆解成可重复解决的问题(最近子问题) 数学归纳法思维 爬楼梯 在第三层的时候,不再是从头思考,而是从已有的结果出发,也就是从第二层和第三层出发

括号的生成 先思考参数应该如何设置,自顶向下编程

然后无脑写模版

第一种思路,先把所有可能都输出了,然后在return的时候,过滤结果

第二种思路,在中间过程中就把不合法的删除,规则是右括号小于等于左括号

为什么7行代码可以解决复杂的问题,因为人脑老是习惯暴力递归,而没有思考重复性。

验证二叉搜索树 方法1: 根据二叉搜索树定义

方法2: 中序遍历,输出有序数组

二叉树最大深度和最小深度 关键是叶子节点定义,最大深度肯定是探到底,因此最后的节点必然是叶子结点。但是对于最小深度,并不是最前面的节点就算是最小深度的节点了。比如下面这颗树,虽然9和20都算出来是2,但是20不符合要求,9才是需要的节点。

3

/ \ 9 20 / 15 因此都为空,返回+1,一个为空一个不为空,发挥不为空节点后续+1;

其他 Cpp的新的for循环: for( auto str:strs ).

新建容器vector的一种方法vect or vec(1, str), 结果是长度为1,默认为str的vector

算术基本定理,又称为正整数的唯一分解定理,即:每个大于1的自然数,要么本身就是质数,要么可以写为2个以上的质数的积,

image