剑指offer 61~67

61.请实现两个函数,分别用来序列化和反序列化二叉树

public class Solution {
    String Serialize(TreeNode root) {
        if(root == null) return "#";
        return root.val + "," + Serialize(root.left) + "," + Serialize(root.right);
    }
    
    int index = -1;
    TreeNode Deserialize(String str) {
        if(str == null) return null;
        String[] s = str.split(",");
        return Deserialize(s);	
    }
    TreeNode Deserialize(String[] str) {
        index++;
        if(!str[index].equals("#")){
            TreeNode node = new TreeNode(Integer.parseInt(str[index]));
            node.left = Deserialize(str);
            node.right = Deserialize(str);
            return node;
        }
        return null;
    }
}

62.给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。

import java.util.*;
public class Solution {
    List<TreeNode> list = new ArrayList<>();
    TreeNode KthNode(TreeNode pRoot, int k){
        sort(pRoot);
        if(k <= 0 || k > list.size()) return null;
        return list.get(k-1);
    }
    void sort(TreeNode root){
        if(root != null){
            sort(root.left);
            list.add(root);
            sort(root.right);
        }
    }
}

63.如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

import java.util.*;
public class Solution {
    PriorityQueue<Integer> high = new PriorityQueue<>();//后半部分小根堆,从小到大
    PriorityQueue<Integer> low = new PriorityQueue<>(new Comparator<Integer>(){
        public int compare(Integer o1,Integer o2){
            return o2 - o1;
        }
    });//前半部分大根堆,从大到小
    public void Insert(Integer num) {
        low.offer(num);
        high.offer(low.poll());
        if(high.size()>low.size()){
            low.offer(high.poll());
        }
    }
    public Double GetMedian() {
        return low.size() == high.size() ? 
        (low.peek() + high.peek())/2.0 : low.peek()*1.0;
    }
}

64.给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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.*;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size){
        ArrayList<Integer> list = new ArrayList<>();
        if(size <= 0 || size > num.length) return list;
        PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>(){
            public int compare(Integer o1,Integer o2){
                return o2 - o1;
            }
        });
        for(int i = 0; i < size ; i++){
            queue.offer(num[i]);
        }
        list.add(queue.peek());
        for(int i = size; i < num.length; i++){
            queue.remove(num[i - size]);
            queue.offer(num[i]);
            list.add(queue.peek());
        }
        return list;
    }
}

65.题目描述请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如
|a b c e|
|s f c s |
|a d e e|
矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

public class Solution {
    int[][] visit ;
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str){
        visit = new int[rows][cols];
        char[][] arr = new char[rows][cols];
        for(int i = 0;i < rows ;i++){
            for(int j = 0;j < cols;j++){
                arr[i][j] = matrix[i * cols + j];
            }
        }
        for(int i = 0;i < rows ;i++){
            for(int j = 0;j < cols;j++){
                if(find(arr,str,rows,cols,i,j,0)){
                    return true;
                }
            }
        }
        return false;
    }
    public boolean find(char[][] arr,char[] str,int rows, int cols,int h,int l,int index){
        if(index >= str.length) return true;
        if( h < 0 || h >= rows || l < 0 || l >= cols ||
           arr[h][l] != str[index] || visit[h][l] == 1){
            return false;
        }
        visit[h][l] = 1;
        boolean isPath = find(arr,str,rows,cols,h-1,l,index+1)||
            find(arr,str,rows,cols,h+1,l,index+1)||
            find(arr,str,rows,cols,h,l-1,index+1)||
            find(arr,str,rows,cols,h,l+1,index+1);
        visit[h][l] = 0;
        return isPath;
    }
}

66.地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

public class Solution {
    public int movingCount(int threshold, int rows, int cols){
        if(threshold <= 0){
            return 0;
        }
        int[][] visit = new int[rows][cols];
        return move(threshold,rows,cols,0,0,visit) + 1;
    }
    private final int[] dx = {-1,1,0,0};
    private final int[] dy = {0,0,-1,1};
    public int sum(int x){
        int ans = 0;
        while(x > 0){
            ans += x%10;
            x /= 10;
        }
        return ans;
    }
    public int move(int threshold, int rows, int cols,int h,int l,int[][] visit){
        visit[h][l] = 1;
        int count = 0;
        for(int i = 0;i < 4;i++){
            int x = h + dx[i];
            int y = l + dy[i];
            if(x >= 0 && x < rows && y >= 0 && y < cols &&
               visit[x][y] != 1 && sum(x) + sum(y) <= threshold){
                count += move(threshold,rows,cols,x,y,visit) + 1 ;
            }
        }
        return count;
    }
}

67.给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]xk[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

public class Solution {
    public int cutRope(int target) {
        if(target <= 3){
            return target - 1;
        }
        int i = 1;
        while(target > 4){
            i *= 3;
            target -= 3;
        }
        return target * i;
    }
}
发布了42 篇原创文章 · 获赞 13 · 访问量 6503

猜你喜欢

转载自blog.csdn.net/weixin_43508555/article/details/104514636