1、序列化二叉树
题目描述:
请实现两个函数,分别用来序列化和反序列化二叉树
思路:
1、从二叉树到序列化:
将二叉树的结点依次加入ArrayList,同时,如果该结点!=null,那么将它的左右子结点加入ArrayList,并得到序列化"val,";如果该结点==null,那么得到序列化"#,"
2、从序列化到二叉树
先得到所有结点(不带左右子结点)加入ArrayList,然后将结点依次取出,为它们附上左右子结点。
代码:
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
import java.util.ArrayList;
public class Solution {
String Serialize(TreeNode root) {
String result = "";
ArrayList<TreeNode> nodes = new ArrayList<>();
nodes.add(root);
for(int i=0;i<nodes.size();i++){
TreeNode node = nodes.get(i);
if(node==null){
result = result + "#,";
}else{
result = result + node.val + ",";
nodes.add(node.left);
nodes.add(node.right);
}
}
result = result.substring(0,result.length()-1);
return result;
}
TreeNode Deserialize(String str) {
ArrayList<TreeNode> nodes = new ArrayList<>();
String[] token = str.split(",");
if(token.length==0){
return null;
}
for(int i=0;i<token.length;i++){
if(token[i].equals("#")){
nodes.add(null);
}else{
nodes.add(new TreeNode(Integer.parseInt(token[i])));
}
}
int index = 1;
for(int i=0;i<nodes.size();i++){
TreeNode node = nodes.get(i);
if(node!=null){
node.left = nodes.get(index);
index++;
node.right = nodes.get(index);
index++;
}
}
return nodes.get(0);
}
}
2、二叉搜索树的第K个结点
题目描述:
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。
思路:
二叉搜索树的中序遍历的第K个就是想要找的结点。
找node.left或者node.right第K个结点。使用一个计数器count来记录个数。
1、先找node.left,如果返回值为null则表示左结点不是第K个结点,count+1
2、如果count的值和K相等,则说明当前结点就是要找的结点
3、如果count的值不等于K,增继续找当前结点的右子结点
代码:
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
int count = 0;
TreeNode KthNode(TreeNode pRoot, int k)
{
if(pRoot==null){
return null;
}
TreeNode node = KthNode(pRoot.left,k);
if(node!=null) return node;
count++;
if(count==k)return pRoot;
node = KthNode(pRoot.right,k);
if(node!=null) return node;
return null;
}
}
3、数据流中的中位数
题目描述:
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
思路:
在插入时同时排序即可。
代码:
import java.util.ArrayList;
import java.util.Collections;
public class Solution {
ArrayList<Integer> list = new ArrayList<>();
public void Insert(Integer num) {
if(list.size()==0){
list.add(num);
}else{
int index = list.size();
for(int i=0;i<list.size();i++){
if(list.get(i)<num){
continue;
}else{
index = i;
break;
}
}
list.add(index,num);
}
/*
list.add(num);
Collections.sort(list);
*/
}
public Double GetMedian() {
if(list.size()%2==0){
return (list.get(list.size()/2)+list.get(list.size()/2-1))/2.0;
}else{
return list.get(list.size()/2)*1.0;
}
}
}
4、滑动窗口的最大值
题目描述:
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
代码:
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> result = new ArrayList<>();
if(size==0){
return result;
}
for(int i=0;i<=num.length-size;i++){
int maxNum = num[i];
for(int j=i;j<i+size;j++){
if(num[j]>maxNum){
maxNum = num[j];
}
}
result.add(maxNum);
}
return result;
}
}
5、矩阵中的路径
题目描述:
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。
例如
a b c e
s f c s
a d e e
这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
思路:
回溯法。通过上下左右递归看是否字符串匹配,如果当前字符不匹配或已经被访问则false。如果递归匹配到末尾,则true。
代码:
public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
{
boolean flag[] = new boolean[matrix.length];
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
if(findPath(matrix,rows,cols,str,i,j,0,flag)){
return true;
}
}
}
return false;
}
public boolean findPath(char[] matrix, int rows, int cols, char[] str,
int i, int j, int k, boolean[] flag){
int index = i*cols+j;
if(i<0||i>=rows||j<0||j>=cols||matrix[index]!=str[k]||flag[index]){
return false;
}
if(k==str.length-1) return true;
flag[index] = true;
if(findPath(matrix,rows,cols,str,i-1,j,k+1,flag)||
findPath(matrix,rows,cols,str,i+1,j,k+1,flag)||
findPath(matrix,rows,cols,str,i,j-1,k+1,flag)||
findPath(matrix,rows,cols,str,i,j+1,k+1,flag)){
return true;
}
flag[index] = false;
return false;
}
}
6、机器人运动范围
题目描述:
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
思路:
类似于上一题,上下左右移动,若已经访问或大于K则返回0,否则加1。
代码:
public class Solution {
public int movingCount(int threshold, int rows, int cols)
{
boolean[][] flag = new boolean[rows][cols];
return move(threshold,rows,cols,flag,0,0);
}
public int move(int threshold, int rows, int cols,boolean[][] flag,
int i, int j){
if(i<0||i>=rows||j<0||j>=cols||
getNum(i)+getNum(j)>threshold||flag[i][j]){
return 0;
}
flag[i][j] = true;
return move(threshold,rows,cols,flag,i-1,j)+
move(threshold,rows,cols,flag,i+1,j)+
move(threshold,rows,cols,flag,i,j-1)+
move(threshold,rows,cols,flag,i,j+1)+1;
}
public int getNum(int num){
if(num<10){
return num;
}
String result = ""+num;
int total = 0;
for(int i=0;i<result.length();i++){
total+=(result.charAt(i)-'0');
}
return total;
}
}