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;
}
}