劍指Offer行榜【牛客網】練習(十四)

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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章