LeetCode 942. 增减字符串匹配 / 1728. 猫和老鼠 II(博弈,不会) / 449. 序列化和反序列化二叉搜索树

942. 增减字符串匹配

2022.5.9 每日一题

题目描述

由范围 [0,n] 内所有整数组成的 n + 1 个整数的排列序列可以表示为长度为 n 的字符串 s ,其中:

如果 perm[i] < perm[i + 1] ,那么 s[i] == ‘I’
如果 perm[i] > perm[i + 1] ,那么 s[i] == ‘D’

给定一个字符串 s ,重构排列 perm 并返回它。如果有多个有效排列perm,则返回其中 任何一个 。

示例 1:

输入:s = “IDID”
输出:[0,4,1,3,2]

示例 2:

输入:s = “III”
输出:[0,1,2,3]

示例 3:

输入:s = “DDI”
输出:[3,2,0,1]

提示:

1 <= s.length <= 10^5
s 只包含字符 “I” 或 “D”

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/di-string-match
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

贪心,想到思路就不难了

class Solution {
    public int[] diStringMatch(String s) {
        //这个题竟然是个简单题,一时间竟然不知道怎么做
        //想到一个思路
        //就是每次放只放当前最大和最小数
        //例如第一个例子,第一个字母是I,那么说明左边的小,所以放0
        //第二个字母是D,那么说明左边的大,放当前最大,也就是4
        //第三个字母I,放1;
        //这样放置,可以保证每两个元素是肯定满足条件的,
        //而因为每次放的要不是最小要不是最大,可以保证不会影响到后面的放置
        //那么依次类推,整个都是满足条件的

        int n = s.length();
        int min = 0;
        int max = n;
        int[] res = new int[n + 1];
        for(int i = 0; i < n; i++){
            if(s.charAt(i) == 'I'){
                res[i] = min;
                min++;
            }else{
                res[i] = max;
                max--;
            }
        }   
        res[n] = min;
        return res;
    }
}

1728. 猫和老鼠 II

2022.5.10 每日一题

题目描述

一只猫和一只老鼠在玩一个叫做猫和老鼠的游戏。

它们所处的环境设定是一个 rows x cols 的方格 grid ,其中每个格子可能是一堵墙、一块地板、一位玩家(猫或者老鼠)或者食物。

  • 玩家由字符 ‘C’ (代表猫)和 ‘M’ (代表老鼠)表示。
  • 地板由字符 ‘.’ 表示,玩家可以通过这个格子。
  • 墙用字符 ‘#’ 表示,玩家不能通过这个格子。
  • 食物用字符 ‘F’ 表示,玩家可以通过这个格子。
  • 字符 ‘C’ , ‘M’ 和 ‘F’ 在 grid 中都只会出现一次。

猫和老鼠按照如下规则移动:

  • 老鼠 先移动 ,然后两名玩家轮流移动。
  • 每一次操作时,猫和老鼠可以跳到上下左右四个方向之一的格子,他们不能跳过墙也不能跳出 grid 。
  • catJump 和 mouseJump 是猫和老鼠分别跳一次能到达的最远距离,它们也可以跳小于最大距离的长度。
  • 它们可以停留在原地。
  • 老鼠可以跳跃过猫的位置。

游戏有 4 种方式会结束:

  • 如果猫跟老鼠处在相同的位置,那么猫获胜。
  • 如果猫先到达食物,那么猫获胜。
  • 如果老鼠先到达食物,那么老鼠获胜。
  • 如果老鼠不能在 1000 次操作以内到达食物,那么猫获胜。

给你 rows x cols 的矩阵 grid 和两个整数 catJump 和 mouseJump ,双方都采取最优策略,如果老鼠获胜,那么请你返回 true ,否则返回 false 。

示例 1:

在这里插入图片描述
输入:grid = [“####F”,“#C…”,“M…”], catJump = 1, mouseJump = 2
输出:true
解释:猫无法抓到老鼠,也没法比老鼠先到达食物。

示例 2:

在这里插入图片描述
输入:grid = [“M.C…F”], catJump = 1, mouseJump = 4
输出:true

示例 3:

输入:grid = [“M.C…F”], catJump = 1, mouseJump = 3
输出:false

示例 4:

输入:grid = [“C…#”,“…#F”,“…#”,“M…”], catJump = 2, mouseJump = 5
输出:false

示例 5:

输入:grid = [“.M…”,“…#…”,“#…#.”,“C#.#.”,“…#F”], catJump = 3, mouseJump = 1
输出:true

提示:

rows == grid.length
cols = grid[i].length
1 <= rows, cols <= 8
grid[i][j] 只包含字符 ‘C’ ,‘M’ ,‘F’ ,‘.’ 和 ‘#’ 。
grid 中只包含一个 ‘C’ ,‘M’ 和 ‘F’ 。
1 <= catJump, mouseJump <= 8

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/cat-and-mouse-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

一眼看过去就不会做的题,不过范围好像不大,能挣扎一下
记得当时猫和老鼠那道题就不怎么会做,这直接来了个更难的…先收藏了

449. 序列化和反序列化二叉搜索树

2022.5.11 每日一题

题目描述

序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。

设计一个算法来序列化和反序列化 二叉搜索树 。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。

编码的字符串应尽可能紧凑。

示例 1:

输入:root = [2,1,3]
输出:[2,1,3]

示例 2:

输入:root = []
输出:[]

提示:

树中节点数范围是 [0, 10^4]
0 <= Node.val <= 10^4
题目数据 保证 输入的树是一棵二叉搜索树。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/serialize-and-deserialize-bst
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

我的常规想法,也是题解里面的一般做法

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Codec {
    //直接填充空节点的序列化操作也是没问题的
    //但是这里给的是二叉搜索树,利用左节点小,右节点大的特点,可以方便的反序列化
    //序列化直接前序遍历
    //反序列化的时候,先找根。然后根后面接着的就是左边节点,比它大的就是右边结点
    //主要是反序列化难写点

    
    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        if(root == null)
            return "";
        StringBuffer sb = new StringBuffer();
        preOrder(sb, root);
        return sb.substring(0, sb.length() - 1);
    }
    public void preOrder(StringBuffer sb, TreeNode root){
        if(root == null)
            return;
        sb.append(root.val + ",");
        preOrder(sb, root.left);
        preOrder(sb, root.right);
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        //System.out.println(data);
        if("".equals(data))
            return null;
        String[] ss = data.split(",");
        int l = ss.length;
        int[] nums = new int[l];
        int idx = 0;
        for(String s : ss){
            nums[idx++] = Integer.parseInt(s);
        }
        return build(nums, 0, l - 1);
    }

    public TreeNode build(int[] nums, int left, int right){
        if(left > right)
            return null;
        TreeNode root = new TreeNode(nums[left]);
        //找第一个比它大的
        int i = left + 1;
        int j = right;
        while(i < j){
            int mid = (j - i) / 2 + i;
            if(nums[mid] < nums[left]){
                i = mid + 1;
            }else{
                j = mid;
            }
        }

        //找到的点需要判断一下
        //如果还是小于,那么说明没有大于它的
        if(i <= right && nums[i] < nums[left]){
            root.left = build(nums, left + 1, i);
            root.right = null;
            return root;
        }
        root.left = build(nums, left + 1, i - 1);
        root.right = build(nums, i, right);
        return root;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec ser = new Codec();
// Codec deser = new Codec();
// String tree = ser.serialize(root);
// TreeNode ans = deser.deserialize(tree);
// return ans;

然后看了官解的后序遍历,是用栈来代替查找中间数,这个很巧妙
具体来说,就是栈每次弹出的都是根节点,然后利用这个根节点确定下面节点的范围,然后递归
这样不需要查找的话,时间复杂度就能降低

那么想想先序遍历加队列的方式可以吗,应该也行。下面是代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Codec {
    //直接填充空节点的序列化操作也是没问题的
    //但是这里给的是二叉搜索树,利用左节点小,右节点大的特点,可以方便的反序列化
    //序列化直接前序遍历
    //反序列化的时候,先找根。然后根后面接着的就是左边节点,比它大的就是右边结点
    //主要是反序列化难写点

    
    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        if(root == null)
            return "";
        StringBuffer sb = new StringBuffer();
        preOrder(sb, root);
        return sb.substring(0, sb.length() - 1);
    }
    public void preOrder(StringBuffer sb, TreeNode root){
        if(root == null)
            return;
        sb.append(root.val + ",");
        preOrder(sb, root.left);
        preOrder(sb, root.right);
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        //System.out.println(data);
        if("".equals(data))
            return null;
        String[] ss = data.split(",");
        int l = ss.length;
        int[] nums = new int[l];
        int idx = 0;
        Queue<Integer> queue = new LinkedList<>();
        for(String s : ss){
            queue.offer(Integer.parseInt(s));
        }
        return build(queue, -1, 10001);
    }

    public TreeNode build(Queue<Integer> queue, int low, int up){
        if(queue.isEmpty() || queue.peek() < low || queue.peek() > up)
            return null;
        
        int top = queue.poll();
        TreeNode root = new TreeNode(top);
        
        root.left = build(queue, low, top);
        root.right = build(queue, top, up);
        return root;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec ser = new Codec();
// Codec deser = new Codec();
// String tree = ser.serialize(root);
// TreeNode ans = deser.deserialize(tree);
// return ans;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值