- 进阶链表
- 进阶树
- 进阶图
- 进阶链表
双向链表,
例题 430 . dfs即可
异或链表
- 进阶树
segement tree
, 节点里面能存储区间
303. 问题在于如果调用很多次怎么办,可以用新的存储空间来存储,
Trie: 字典树
平衡树
N 叉树
B树
红黑树
双向链表,
例题 430 . dfs即可
异或链表
segement tree
, 节点里面能存储区间
303. 问题在于如果调用很多次怎么办,可以用新的存储空间来存储,
Trie: 字典树
平衡树
N 叉树
B树
红黑树
maimimum moving avarage:
maimimum moving max:
:可以一用heap么。不可以,因为不知道pop的是不是头
:可以用sorted stack
:思路:,squential,,,每到一个ele时,有可能时后面max,所以先判断前面《的话,删掉然后加上本个ele,》的话直接加上,因为stack村的是有可能是max的东西。 如果move 后out of window,先删除对应操作,这样stack顶永远是max当前window。
这样用的就是deque,或者double linklist,
out of window 的时候要注意判断头部是不是out? index stack:记录index,,然后j-i>=k,就是out of window
dfs stack的模板:
DFS(s,g):
stack s,
end constraint g,
initilaize s: push first node to s and visited hashet, parent hashmap.
while(stack not empty:){
pop node;
if(cur==G) return
for (each neighburs not visited){
add neighvbut to visited
add cur as parent of n
push n onto stack
1.Maze , 2D array, 赵路径
例题:maze II。
使用的三个数据结构:“hash set, bisited”"hahmap,path" "stack或者queue"
C++中可以用vector<bool>也可以待变visited
看题目要求是不是要path,如果去找neighbour,
Maze中可以用i,j+-1,或者用一个direction矩阵代表更多方向,然后for循环去迭代方向
2. 2D array all points
flood fill. 填色
思路:single point dfs/bfs都可以, 时间complexity都一样 |V|+|E|.
dfs 的recursion的代码量简洁。
例题:number of island。
思路,for矩阵,然后dfs开始,碰到1就边0,然后整体计算number
,all points 的dfs就是for single point的dfs
3。 friend circles, 邻接矩阵,像但由于是一个对角线的all points
可以用dfs找path,如果能有一条path,说明一个circle,没有说明第二个circle
for i 是代表人,利用visted代表circle,dfs之后count++就是circle的数量
4. 例题:pacific atlantic water flow.
还可以用dp的结果,避免重复计算
,可以:aLL points+DP
DP里面不同的值来代表不同的意思
还要回溯,底部true,回溯回去也要true,一路的retrun
selected point:
5. non 2D array
例题:word ladder
思路:每个word是一个vertex,
可以用stack。
要解决的问题:neighbour,hashset,hahmap,start
这里难点在于如何判断neighbour,
思路,可以对于当前单词进行每个位置的字母改变,然后find 字典里是否有出现。
BFS可以求最短路径
属于2 pointer的子集,都是从前往后走
例题:remove duplicated from sorted array
思路:end往后走直到最后一个different。然后start是第一个diff, 所以in place的算法是吧dif的ele move到start,start+1.
so start: is the first distinct的position
end是来判断,if dif的话就跟start换位置,if equal则end+1
思路:hashset可以用,o(n)和o(n)
duplicates可以用hashtable
例题:如果diuplicate的出现次数k,
思路:那么判断start的前面有几个,或者判断end-2和end是否一样或者j-i>=2
例题:remove element:(inplace)
start是第一个1的位置,然后end是non-1,然后swap,然后i+1,j都要加1,
所以一开始的start是先找到对应1(要先for),也可以不用
for(int i,j;i<len&j<len;j+1){ if (nums[i]!=1) start+=1}
例题: maximum average subarray.
start 是maxim的start。 end++,一个global max,然后更新start。end往前数,然后maximum可以减去头+尾。单个for就可以
思路:也可以累加,然后减去前面k的元素当前的和,然后就是当前的k个和
例题:sliding window 3
思路:rolling hash,利用hashcode计算,而且可以偷懒,类似于上面的去头加尾
例题:subarrayproduct less than k
start和end,end先移动到最小不满足,然后startmove到满足,这其中每一个sub都是满足的
但是计算的是number,而不是每一个subarray,所以j-i+1是多的validwindow,计算
例题: sliding window 2:
例题:minimum size subarray sum
思路:start,end中间的和,global存储当前的最短,if sum>k,则start+1. 然后继续end+1判断。 start<end肯定
for内嵌while (i),但是i和j相对独立,所以时间复杂度是O(n)
例题:sliding window IV
例题:longest substring without repeating characters
区分subsequence和esubarray
遇到duplicate,repeateing,exist,unique都可以用hashmap来解决
例题:47 permutation 2:
input 有重复,有一个i-1的non-visited判断
例题:131,palindrome partition,实际上是个组合问题,可以用组合模板,先判断前面的substring的是不是palidrome,然后对于后面的substring进行dfs。
优化:dp的memorization将已经pali的存起来
例题:44 .1h
add and search words
复杂度:O(M)就是最长单词长度,space复杂度:字母表长度*key——length(比如说一个char)*key个数
例题:add and search words
要在对应word的结尾标记一个证明是一个word。
trie是用hashmap实现的
例题:auto-complete system:
例题:word search 2. 212.因为input是字符串,所以可以用trie来节省一部分时间,
回溯的时候要标记回来,visited.true. dfs(),
visited=false
trie:
class TrieNode{TrieNode[] next= new TriNode[26], String word},要标记当前是不是一个word,这就是flag,可以灵活变通,也可以把当前的词存进去
notability
例题329.1h17min
valid 括号问题 例题
背包问题
例题:301
DFS,去重复剪纸
BFS?
经典:number of island
例题:827
making a large island
复杂度:n2,当前点
例题:312
例题: 子问题互相影响,dp[i][k-1]
dp[k+1][j],定义是两边不能炸
tree上边的tranversla和divi&&conquer就是DFS
BFS,binarty tree level-order tranversal一层一层的走就是
图和tree: tree,没有cyce,dfs不会重复,图可能有环,可能死循环如果不记录的话
where you can search:tree,graph,Combination of Linear structures(array,string, number)
LTC 102: binary tree level order Traversal
.BFS用到了queue,FIFO
stack可以实现DFS,不过先right child然后leftchild,这样可以保证print先left在右,因为stack的先入后出
BFS有模板
1h27 例题: 200 number_of island,可以使用DFS,或者queue的BFS
1h40 例题:78subsets。 sort,避免重复的number。
使用递归实现combination,复杂度exponential
所有combination的题目有一个模板2h06
先sort!!!
result。add中 new arraylist(subset)?deep copy
startindex看看是否可以服用,可以复用,i不变否则i+1
例题:90subset2. 2h09, 加上一句判断现在和前者是否一样,并且不能越界。
这样就不用单独新建一个vecotr去重了
例题:39 combination sum
40Com sum2. 右duplicate
216 com sum3. size=k的sum=target
helper必须传的参数,startindex,原始array,每层的solution,总的result
46.permutation。2h31min
所有的数都要被选
permutation 2例题,
算法原理:
算法复杂度:
例题:longest in creaseing subsquence
greedy,使用的话要证明一下多个状态可以用一个状态解释
例题: wiggle subsqueece
例题:背包问题
例题:96 unique binary search tree
numtrees(n-2)*num(1)+.... numtree(1)*nums(n-2), 左右子树排列数,因为bst型确定了,数也就确定了
例题:括号问题,和上面类似
例题:edit 。。。。 状态转移方程。 1h23 min
例题: pattern matching :44 wildcard mathcing
例题:permutations for di sequence
贪心算法:
定义:选择的贪心策略必须具有无后效应,寄某个状态之前的过程不会影响以后的状态,只与当前状态有关。
需要判断一下当前的最优解是不是最终的最优解。
最优子结构:当问题的最优解包含子问题的最优解的时候
局限性:
上节课的dikistra,prim,krukal算法都是贪心算法。
上述算法也都有一些限制条件,就是为了约束最后的最优解的
大部分例题都能有DP解
例题:455: assign cookies。40min
小给小,大给大,可以sort后双指针遍历人和饼干,
122:Best time to but and Sell stockII
53:
134:gas
55: jump game。 只是求哪里开始可以完成目的可以贪心,但是求最小步骤不能用贪心算法。
总结:贪心算法主要是针对一维问题,不需要独立,DP是前后有关系,需要记录
讲一个问题拆分成几个子问题,分别求解子问题。
步骤:
重点:初始状态,和状态转移方程。
基本要素:
要学会问题归类:尤其是DP问题。例如二维DP,写两层循环。。
一般是最大利润或者最小误差等
例题:198:house robber。
初始条件:最大财务=0.
状态转移方程:每次到房子的时候利用和前面房子的关系,限制条件:不能连续抢。一般来说最后求最大财务数,每一步也要求最大财务书。
对每个房子状态两个:抢或者不抢,强的话:i-2的财务+当前财务。 不强的话:i-1的财务。
一般不用矩阵,因为只跟前一个或两个有关系。直接用几个变量表示就行。 矩阵的话一般是跟前n个有关。
状态转移,当前状态买,卖,不做。
初始值:一般来说是最大利润,
然后加上边界调节。有可能要加矩阵的维度,eg.cooldown
例题集合:1h24min
121.。。。。。。
贪心算法和动态规划的关系:
相同点
不同点:
每一步的贪心决策都无法改变,之前的最优解不做保留,每一步的最优解一定包括上一步的最优解
(只要掌握动态规划就好,)
最多区间调度问题,可以通过贪心算法1h48min
最大区间:只能用DP
例题:56 merge intervals. 2h07min
435
452
252
715 Hard
背包问题(leetcode 一般只有01背包和完全背包问题)。
2h17min,记得V的循环顺序
lintcode有很多例题
大公司更偏向算法和基础知识掌握,比如刷题更针对大公司。 算法和数据结构。 bar:focus 在解题能力,没有system-design要求对刚毕业的人。45分钟解答出一到两道1-2难度的题、有可能有hard。
大公司即便对计算机没有极大的要求也可以通过面试进去。
小公司要求项目能力,额外学一些java在工业界,安卓等上面的应用。
Sublime text, VS code build java。IDE有联想功能可能更方便
分为:object, method, class
import java.utils.*;
import java.io.*;
pubilc class Helloworld {
public main( String[] args ) {
System.out.print.....
}
}
String s; s=new String(); 合并成一:String s=new String("Hello")
例子: String s2=s 指向同一个object
s2=new String(s); 这两个不一样的object,东西一样。
s2=s.toUppercase(); String s3= s2.concat("!!"); ===s3=s2+"!!" s3和s2不一样的object。s2创造了新的指针,没有改变原来的string。 但这个只是对string成立的,即要想改变string object,只需要create 一个新的 string就行,
class human{
pubilc int age;
pubilc void introduce() { print} 这是method
oublic void copy( Human ori){
age=orig.age}
}
Human amada= new Human();创造一个object
amanda.age=6; 赋值
amade.introduce() ;call method
Human mike= new Human() ; 新的object
mike.copy(amand); 这里mike的变量和amaenda一样
可以自己定义,也有默认,因为上面就是没有外部赋值给一个内部元素,防止崩溃:
public human(int x, string name){
age=x; y=name }
但是注意:Human amada= new Human();这样会报错,和定义的constructor不一样
class human{
pubilc int age;
pubilc human(int givenage){ this.age=givenage, this.name='skkkk'} this是optional
pubilc void chaneg(int age,){
this.age=age}这里this不能省略因为要不然没用age=age
}
可以在不同的objects里面share同样的值
eg. class human{
pubilc static num;
public human(){
num++}这样可以用的统计object数量,因为每个object都有同样的值
pubilc static void printhume(){
num} static method不能pass object,因为这可能导致不同的object的static变量然后出错
}
local: method里面就是method运行完就消失。
instance :非静态:就是只要amanda这个object还在,他就在
static:只要program在运行就一直在,所以不同的object可以share
不是reference to object,例如 int, long, float, 怎么创建: “6”,“3.4”, “true”
object create: new
object define: class definition
initialize: constructor
use: method
例如 string 是一个object,可以 String name="hello"; name ="world"指向了另一个object。
这是java 内置的, 一般string不用写 String name= new String{"hellp"}
Math class.
Integer class.//convert a string to an integer. 注意 Integer.conv("3.14")会报错
&&, ! , 等等操作
x= 3==5 可以直接判断赋值
boolean pass =score <60
if (pass){} else{}
也可以if (score >=60){}更简洁
简介的表达形式:a= x>y ? max(x,z) : max(y,z)
switch (month){
case 2:
a=2; break;
case 4:
case 6:
default: days=2; break;
}
do {} while()起码会run一次,while有可能一次不run
for (initialize; condition; next) {},next 可以省略
fixed number , z在create的时候就确定了
char[] c; // reference to an array
c=new char[4]; //construct and array
c[1]='b';//赋值
小窍门: 判断n的平方根和d比较: d*d <=n因为开平方比较耗资源
two dimensional array is an array of references to arrays. 第一层里面存的是内部array的指针
int[][] pt= new [n][] 这样的话内部矩阵可以不同长度 例如帕斯卡三角, 当然内部长度也可以直接定义
for (int i=0; i<n; i++){
pt[i]=new int[i+1] // 内部
}
更多array declarations:
human[] b={a, mike, new human("me")}
int[][] c= {{7,4,3},{3,3,x},{x+y}}
d= new int[] {3,7}
下面这些都是declaration:没有construct
int[] a,c,b ;/// a,b,c all reference array,不是object
int a[], b,c[][] /// a is 1D,b is not a reference/array
int[] a,b[]/// a is a reference to a 1 D array, b reference a 2D array 很逆天