剑指Offer行榜【牛客网】练习(十四)

28 篇文章 0 订阅
13 篇文章 0 订阅
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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值