初级农民-请到新手上路获取积分
- 积分
- 7
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2023-7-5
- 最后登录
- 1970-1-1
|
7月23日刷题2道
leetcode 417. Pacific Atlantic Water Flow
note1. 再次回顾一下,使用dfs的意义是求解 ***可达性***
note2. 基础知识,"Java: how do I initialize an array size if it's unknown?"
array 和 list 是不一样的概念(url: https://stackoverflow.com/questi ... size-if-its-unknown),url里面第一个解释很好,array如果要扩增size,就是**数据结构**里面学的,copy and paste everything to a new larger array,相较之下,arraylist(属于list)可以automatically resize
note3. 关于list of list的bebug
^ url: https://stackoverflow.com/questi ... aylist-of-arraylist
note4. [我的思路] 创建了一个grid形式的visited,创建了2个dfs(一个pacific, 一个Atlantic), 创建2个dfs的原因是同时到达两边不好标记是否visited,因为走一边不要走重复的路,但是两边交叉是可以走重复的点?
note5. 还是感觉有点神奇,这个也是应用于之前几道DFS,比方传入的一个int[][] heights, dfs以及下面延伸的dfs都可以对其(heights)进行修改
note6. runtime and memory非常不理想,对比cyc2018的答案
6.1 cyc 又是进行了逆向思维,创建了2个boolean 形式的grid
- boolean[][] canReachP = new boolean[m][n];
- boolean[][] canReachA = new boolean[m][n];
6.2 然后分别从两端海岸线(低海拔)倒推水源的高海拔的坐标
6.3 然后把两个grid重叠(即重叠canReachP and canReachA)
6.4 我是传统的思路,循环整个网格,从高海拔到低海拔,如果低海拔靠到海边,就算能流过去(顺着题意做的)
note7. [基础知识] int[][] direction = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
^上述数据结构 + 搭配循环非常好用,for (int[] d : direction){}
note8. 按照cyc的方法重新做一遍
----------------------------------------------------------------
Backtracking 的基础知识
Backtracking(回溯)属于 DFS。
1. 普通 DFS 主要用在**可达性**问题 ,这种问题只需要执行到特点的位置然后返回即可。
2. 而 Backtracking 主要用于求解**排列组合**问题,例如有 { 'a','b','c' } 三个字符,求解所有由这三个字符排列得到的字符串,这种问题在执行到特定的位置返回之后还会继续执行求解过程。
因为 Backtracking 不是立即返回,而要继续求解,因此在程序实现时,需要注意对元素的标记问题:
- 1. 在访问一个新元素进入新的递归调用时,需要将新元素标记为已经访问,这样才能在继续递归调用时不用重复访问该元素;
- 2. 但是在递归返回时,需要将元素标记为未访问,因为只需要保证在一个递归链中不同时访问一个元素,可以访问已经访问过但是不在当前递归链中的元素。
----------------
[back to back swe]
1. 3 keys of backtracking : choices; constraints; goal
2. 演讲者的意思这个每一个都需要试错(一个grid),所以runtime 会是exponential
3. https://www.youtube.com/watch?v= ... kvnOCTI&index=9
--------------------------------------------------------------
leetcode 17. Letter Combinations of a Phone Number
Note1. 单单就针对这道题给的第一个例子而言,如果给2位数,那就是2重for循环,如果给3位数,那就是3重for循环,以此类推[但是这样解题肯定是不对的...]
Note2.
2.1 Cyc2018的做法非常巧妙,正如他所说的,需要deep search的时候需要删减
2.2 删减的原理配合back to back swe 画的树状图就懂了,往下走就增加append,往回走就删减delete,代码非常精妙
2.3 配合swe说的,这个goal(3 keys中的一个)就是填满给定的digits, 所以goal就是我们的base case(有点像之前做的如果碰到边界,那么即可返回)
2.4 代码非常简单,但是choice(3 keys中的一个),就本题而言是for 循环三次
for (char c : letters.toCharArray()) { //选择,就本题而言,每个数字都是三种选择
prefix.append(c); // 添加
doCombination(prefix, combinations, digits); //前面一个digit 已经确定好了,剩下后面位数的digits的排列组合打包交给这个函数
prefix.deleteCharAt(prefix.length() - 1); // 删除,这个删除是为了方便下一次循环使用这个slot
}
Note3. 写代码的细节
3.1 cyc2018在呼叫函数的时候,传入参数直接就是一个new StringBuilder()
3.2 如何char的single quote? --> (2个char相减)'2'-'0' 这样可以得到int 2
3.3 把一个string 变为array of char 有一个内置函数 letters.toCharArray()
3.4 跟所有的recursive 函数一样,(?)感觉就是需要写一个局部处理措施,然后定好base case 知道在哪里停下来,剩下交给函数内部自己处理
3.5 cyc 一一对应的index 细节也非常巧妙 因为根据题意,本来就是一一对应的,(ie: char cur_char = digits.charAt(partial_result.length());)
Note4. 理解Stringbuilder 和String 是类似的,也是一种class, 比string 高级的在于,有很多方法可以用,可以迅速修改string
^ https://www.geeksforgeeks.org/st ... java-with-examples/
^ https://docs.oracle.com/javase/8 ... /StringBuilder.html
^ 更多方法看官网介绍, 就这道题而言,因为最终函数返回的List<String>,所以还需要把stringbuilder class转化为string |
|