1.栈与队列
1.1 猫狗队列
新增队列对象 class PetEnterQueue{ Pet pet, int count } count 为时间戳
----》class DogCatQueue{ queue<PetEnterQueue > dog,queue<PetEnterQueue > dog cat, int count }
1.2 汉诺塔
process(num,lef,middle,right,from,to){
process(num-1,left, midle.right,from,to)
left to middle
process(num-1,left, midle.right,to,from)
middle to right
process(num-1,left, midle.right,from,to)
}
2.链表问题
反转单向链表: tmp = cur.next -> cur.next = pre - > pre = cur -> cur = tmp
约瑟夫问题 :Node head , int m - > last = head
last = last.next 但是 ++n == m ----> last.next = head.next (跳过head)
head = last .next 新头节点(无论是跳过还是不跳过,都是last.next)。
3.二叉树问题
3.1 最大搜索二叉子树 --后序遍历
public Node biggestSubBST(node head){
int [] record = new int[3];
return posorder(head , record);
}
posorder( head ,record){
if head == NULL{
record[0]=0
record[1] =max
record[2] = min
}
value = head.value
lBST = posorder(left,record)
lsize = record[0]
lmin = record[1]
lmax = record[2]
rBST = posorder(right,record)
rsize = record[0]
rmin = record[1]
rmax = record[2]
record[1] = min(lmin,value)
record[2] = max(rmax,value)
if ( rmin > value && lmax <value){
record = lsize +rsize +1
return head
}
}
3.2 层打印: queue 不断push 。
3.3 平衡二叉树:左右子树高度差
getheight ( node , level, bool res)
{
if node =NULL
return level
getheight(node.left,level+1,res)
gethegith(node.right,level+1.res)
if abs(left -right) >1 : res = false
return max(left,right)
}
3.4 完全二叉树:层遍历,若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
lnode ==null && rnode != null return false
lnode !=null queue.push(lnode)
rnode !=null queue.push(rnode) else leaf = true
4 递归和动态规划
4.1 fn { return f(n-1) + f(n-2)}
4.2 最小路径 new 一个 d[i][j] = min(d[i-1][j] + d[i][j-1]) + m[i][j]
4.3最长公共子序列:
d[i][j] 即str1[0~i]跟str2[0~j]的最长
d[i][j] = max(d[i-1][j], d[i][j-1])
if str1[i] = str2[j] d[i][j] = max[dp[i-1][j-1]+1 , d[i][j]]
4.4最长公共子串 if(str1[i]==str2[j]) d[i][j] = d[i-1][j-1] + 1
4.5 n 皇后问题
int[] record = new int[n]
process (0 , record ,n )
public process( i ,record ,n ){
for j = 0 ;j <n ;j++{
if (isValid(i,j,record )){
process( i+1,record,n) // i+1 是因为再下一行的意思,j+1在j全都递归回来之后,再+1
}
}
}
is Valid( i , j ,record){
for k <i ;i++
if (record[k]==j or abs(k-i) ==abs(record[k] - j) ) return false //同一列 ,或同一斜线 a-i == b-j
return true
}
5.字符串问题
变行词: 用map来count str1 ,再遍历str 不断 map-- ,如果有负则返回
数字字串求和: num = num*10 +cur -> res = res + num and num =0 (及下次如果是字母,res + 0)
字符串转整数 : 判断是否大于 2*32 / 10 或者 等于 2*32 /10 但是 后一位 > 2*32 %10 考虑负数则很有趣
-2147483648 2147483647 则转为负数来处理。
字符串匹配问题:
6. 大数据与空间限制
2GB 从20亿个整数中找到次数最多的。
2^ 32 = 4,294,967,296 = 43亿
假设每个数字都不同 ,则hash key用32位能解决。假设1个数字20亿,也能用32位解决。也就是说一条记录要4B*2 = 8B
8B *1亿 < 8亿B =0.8GB ,所以 20 *0.8 =16GB 所以分成8份即可,每份 大约就2gb内存。是否需要考虑hash的效果,所以取16份?
7. 位操作
swap(a,b) -> a = a^b b = b^a a = a^b
获取不同 与b不同就是 a(交换得到a) 与 b(此时已经是a,再次取反)不同就是a
8.数组和矩阵
求最短通路
1 1 1 1 1
1 0 1 0 1
1 1 1 0 1
0 0 0 0 1
关键在于两个队列来记录走通的位置,然后不断pop出来,用队列是因为要宽度优先。比如 (1,3)这个点肯定是直接往右最快,然后另一条回路到打此点时,发现已经被标记则放弃,这是因为宽度优先,保证了被标记的点必定之前的路径不大于此时的路径。
while(){
1.walkup
2.walk down
3.walk left
4. walk right
}
walk(int pre ,int toR,int toC,int rect [][],int map[][], queR,queC){
到达目的地或者 rect [toR][toC] ==0 或者 Map[][]!=0
return
map[][] = pre +1
queR.add(toR)
queC.add(toC)
}