Algo-C1
1.1 二叉树按层遍历(BFS)
- 针对二叉树的宽度又下班遍历
- 宽度优先遍历常使用队列结构
- 面试中,该类题目常对换行有所要求,即按二叉树的结构打印出各个节点(换行)
思路:
BFS不必多说,用队列完美解决遍历顺序问题。但是如何按照树的结构进行换行符的打印呢?
我们需要2个指针,last:表示当前行最后一个节点,nlast:表示下一行最后一个节点。
当currentNode为last节点时,换行,并将last节点指向nlast节点。
如何保证nlast节点永远是下一行的最后一个节点呢?我们每访问一个节点,都将该节点的孩子节点设置为nlast,当当前行遍历结束时,nlast一定为下一行的最后一个节点。
package algo_course.tree;
import algo_course.models.TreeNode;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* 二叉树广度遍历,按树结构输出结果
* @author NikoBelic
* @create 09/01/2017 00:29
*/
public class VisitTree
{
public static void bfs(TreeNode node)
{
Deque<TreeNode> queue = new ArrayDeque<>();
if (node == null)
return;
queue.add(node);
TreeNode currentNode;
TreeNode last = node;
TreeNode nlast = node;
while (!queue.isEmpty())
{
currentNode = queue.pollFirst();
if (currentNode.left != null)
{
queue.addLast(currentNode.left);
nlast = currentNode.left;
}
if (currentNode.right != null)
{
queue.addLast(currentNode.right);
nlast = currentNode.right;
}
System.out.print(currentNode.value);
if (last == currentNode)
{
System.out.println("");
last = nlast;
}
}
}
public static void main(String[] args)
{
TreeNode root = new TreeNode(0);
TreeNode l = new TreeNode(1);
TreeNode r = new TreeNode(2);
TreeNode ll = new TreeNode(3);
TreeNode lr = new TreeNode(4);
TreeNode rl = new TreeNode(5);
TreeNode rr = new TreeNode(6);
root.left = l;
root.right = r;
l.left = ll;
l.right = lr;
r.left = rl;
r.right = rr;
bfs(root);
}
}
输出
0
12
3456
1.2 二叉树的序列化和反序列化
我们一般将二叉树的结构存储于内存中,但有的时候我们还是需要将其序列化成文件保存其结构。
1、二叉树->字符串(序列化)
2、字符串->二叉树(反序列化)
序列化的方式
- 根据先序遍历
- 根据中序遍历
- 根据后序遍历
- 按层
给定一棵二叉树的头结点head,并已知二叉树的值类型为32为int。请设计一种二叉树序列化和反序列化的方案,并用代码实现。
使用!表示val的结束 例如 12! 使用#表示当前节点为null 例如 #!
按照某种遍历方式(1~4)并结合特殊字符遍历二叉树,将结果保存到字符串中序列化,反序列化时同理。
1.3 字符串的旋转词
例如字符串”1234”,它的旋转词有”1234”,”2341”,”3412”,”4123”
1. 判断str1和str2长度是否相等
2. 如果长度相等,生成str1+str1的大字符串
3. 使用KMP算法判断大字符串是否包含str2
如果对于一个字符串A,将A的前面任意一部分挪到后边去形成的字符串称为A的旋转词。比如A=”12345”,A的旋转词有”12345”,”23451”,”34512”,”45123”和”51234”。对于两个字符串A和B,请判断A和B是否互为旋转词。
给定两个字符串A和B及他们的长度lena,lenb,请返回一个bool值,代表他们是否互为旋转词。
测试样例:
“cdab”,4,”abcd”,4
返回:true
public class Rotation
{
public static boolean chkRotation(String A, int lena, String B, int lenb)
{
if (lena != lenb)
return false;
String bigStr = A + ;
int index = bigStr.indexOf(B);
if (index == -1)
return false;
if (bigStr.substring(index, index + lena).equals(B))
return true;
return false;
}
public static void main(String[] args)
{
chkRotation("PVNMCXZNZBETCM",14,"CNTZXMNZEBMVCd",14);
}
}
1.4 给定一个字符串,在单词间做逆序调整
例如”I love dog” => “dog love I” , “I am a student” => “student a am I”
1.实现将字符串局部所有字符都逆序的函数f
2.利用f将字符串所有字符逆序过来 “god evol I”
3.找到逆序后的字符串中每一个单词的区域,利用f将每一个单词区域逆序 “dog love I”
1.5 给定一个字符串str,和一个整数i。i代表str中的位置,将str[0,i]移动到右侧,将str[i+1,N-1]移动到左侧。
例如 str=”ABCDE” i=2 将str调整为 “DEABC”
要求时间复杂度为O(n),空间复杂度为O(1)
1.6 给定一个字符串型数组strs,请找到一种拼接方式,使得所有字符串拼接起来组成打大字符串会所有可能中字典顺序最小的,并返回这个字符串。
strs=[“abc”,”de”] 可以拼接为”abcde”,”deabc” 显然前者更小
strs[“b”,”ba”] 可以拼接为”bba”,”bab” 显然后者更小
错误解法:
先比较子串字典顺序,字典顺序小的放在前面,上面的bba和bab就是一个反例。
正确解法:
最优时间复杂度为O(N*logN)
比较str1+str2和str2+str1,如果前者小,那么拼接方式选前者