[Leetcode Weekly Contest]260

链接:LeetCode

[Leetcode]2016. 增量元素之间的最大差值

给你一个下标从 0 开始的整数数组 nums ,该数组的大小为 n ,请你计算 nums[j] - nums[i] 能求得的 最大差值 ,其中 0 <= i < j < n 且 nums[i] < nums[j] 。

返回 最大差值 。如果不存在满足要求的 i 和 j ,返回 -1 。

遍历即可。

class Solution {
    public int maximumDifference(int[] nums) {
        int res = -1;
        int n = nums.length;
        for(int i =0;i<n;++i) {
            for(int j=i+1;j<n;++j) {
                if(nums[j] > nums[i]) {
                    res = Math.max(res,nums[j]-nums[i]);
                }
            }
        }
        return res;
    }
}

[Leetcode]2017. 网格游戏

给你一个下标从 0 开始的二维数组 grid ,数组大小为 2 x n ,其中 grid[r][c] 表示矩阵中 (r, c) 位置上的点数。现在有两个机器人正在矩阵上参与一场游戏。

两个机器人初始位置都是 (0, 0) ,目标位置是 (1, n-1) 。每个机器人只会 向右 ((r, c) 到 (r, c + 1)) 或 向下 ((r, c) 到 (r + 1, c)) 。

游戏开始,第一个 机器人从 (0, 0) 移动到 (1, n-1) ,并收集路径上单元格的全部点数。对于路径上所有单元格 (r, c) ,途经后 grid[r][c] 会重置为 0 。然后,第二个 机器人从 (0, 0) 移动到 (1, n-1) ,同样收集路径上单元的全部点数。注意,它们的路径可能会存在相交的部分。

第一个 机器人想要打击竞争对手,使 第二个 机器人收集到的点数 最小化 。与此相对,第二个 机器人想要 最大化 自己收集到的点数。两个机器人都发挥出自己的 最佳水平 的前提下,返回 第二个 机器人收集到的 点数 。

由于机器人只会向下和向右行走,可以遍历每一种情况,计算最优解。另外,在比较第二个机器人不同路线的点数时,可以利用前缀和来优化算法复杂度。

class Solution {
    public long gridGame(int[][] grid) {
        long sum1 = 0, sum2 = Arrays.stream(grid[0]).asLongStream().sum(); // 大数溢出
        int n = grid[0].length;
        long res = Long.MAX_VALUE;
        for(int i=0; i<n; ++i) {
            sum2 -= grid[0][i];
            if(i!=0) sum1 += grid[1][i-1];
            long cur = Math.max(sum1, sum2);
            res = Math.min(res, cur);
        }
        return res;
    }
}

[Leetcode]2018. 判断单词是否能放入填字游戏内

给你一个 m x n 的矩阵 board ,它代表一个填字游戏 当前 的状态。填字游戏格子中包含小写英文字母(已填入的单词),表示 空 格的 ' ' 和表示 障碍 格子的 '#' 。

如果满足以下条件,那么我们可以 水平 (从左到右 或者 从右到左)或 竖直 (从上到下 或者 从下到上)填入一个单词:

  • 该单词不占据任何 '#' 对应的格子。
  • 每个字母对应的格子要么是 ' ' (空格)要么与 board 中已有字母 匹配 。
  • 如果单词是 水平 放置的,那么该单词左边和右边 相邻 格子不能为 ' ' 或小写英文字母。
  • 如果单词是 竖直 放置的,那么该单词上边和下边 相邻 格子不能为 ' ' 或小写英文字母。

给你一个字符串 word ,如果 word 可以被放入 board 中,请你返回 true ,否则请返回 false 。

深度优先遍历。对每一个方格向上,下,左,右遍历判断即可。

class Solution {
    enum Direction
    {
        TOP,DOWN,LEFT,RIGHT;
    }
    public boolean placeWordInCrossword(char[][] board, String word) {
        int n = board.length, m=board[0].length;
        int lenWord = word.length();
        for(int i=0;i<n;++i) {
            for (int j=0; j<m; ++j) {
                if(board[i][j]=='#') continue;
                if((i==0 || board[i-1][j]=='#') && i<=n-lenWord && dfs(board,word,i,j,Direction.DOWN)) return true;
                if((i==n-1 || board[i+1][j]=='#') && i>=lenWord-1 && dfs(board,word,i,j,Direction.TOP)) return true;
                if((j==0 || board[i][j-1]=='#') && j<=m-lenWord && dfs(board,word,i,j,Direction.RIGHT)) return true;
                if((j==m-1 || board[i][j+1]=='#') && j>=lenWord-1 && dfs(board,word,i,j,Direction.LEFT)) return true;
            }
        }
        return false;
    }

    public boolean dfs(char[][] board, String word, int i, int j, Direction dir) {
        int n = board.length, m=board[0].length;
        int lenWord = word.length();
        for(int ind=0;ind<lenWord;ind++) {
            if (board[i][j] != ' ' && board[i][j]!=word.charAt(ind)) return false;
            if(dir == Direction.DOWN) i ++;
            if(dir == Direction.TOP) i --;
            if(dir == Direction.RIGHT) j ++;
            if(dir == Direction.LEFT) j --;
        }
        if(i>=0 && i<=n-1 && j>=0 && j<=m-1 && board[i][j]!='#') return false;
        return true;
    }
}

[Leetcode]2019. 解出数学表达式的学生分数

给你一个字符串 s ,它 只 包含数字 0-9 ,加法运算符 '+' 和乘法运算符 '' ,这个字符串表示一个 合法 的只含有 个位数数字 的数学表达式(比方说 3+52)。有 n 位小学生将计算这个数学表达式,并遵循如下 运算顺序 :

  • 按照 从左到右 的顺序计算 乘法 ,然后
  • 按照 从左到右 的顺序计算 加法 。

给你一个长度为 n 的整数数组 answers ,表示每位学生提交的答案。你的任务是给 answer 数组按照如下 规则 打分:

  • 如果一位学生的答案 等于 表达式的正确结果,这位学生将得到 5 分。
  • 否则,如果答案由 一处或多处错误的运算顺序 计算得到,那么这位学生能得到 2 分。
  • 否则,这位学生将得到 0 分。

请你返回所有学生的分数和。

逆波兰表达式+区间DP。计算表达式的正确结果可以使用逆波兰表达式。而计算由 一处或多处错误的运算顺序得到的 错误答案,则可以采取分治的方法,即每一步选择第几个运算符为当前运算,将字符串分为左右两边,再对左右两边的字符串递归求解,由于分解过程中存在分解相同的情况,可以用map作为记忆化存储。

class Solution {
    HashMap<String, Set<Integer>> hash = new HashMap<>();//用于记忆化搜索
    //计算表达式的正确值
    public int result(String s){
        Deque<Integer> q = new LinkedList();
        Deque<Character> cq = new LinkedList();
        int idx = 0;
        for(int i = 0;i < s.length();i ++){
            if(s.charAt(i) >= '0' && s.charAt(i) <= '9'){
                q.offerFirst(s.charAt(i) - '0');
                if(!cq.isEmpty() && cq.peekFirst() == '*'){
                    int n1 = q.pollFirst();
                    int n2 = q.pollFirst();
                    q.offerFirst(n1 * n2);
                    cq.pollFirst();
                }
            }else{
                cq.offerFirst(s.charAt(i));
            }
        }
        while(!cq.isEmpty()){
            int n1 = q.pollFirst();
            int n2 = q.pollFirst();
            q.offerFirst(n1 + n2);
            cq.pollFirst();
        }
        return q.peekFirst();
    }


    public int scoreOfStudents(String s, int[] answers) {
        var nums = new ArrayList<Integer>();
        var ops = new ArrayList<Character>();
        int trueAnswer = result(s);
        for(int ind=0; ind<s.length();++ind){
            if((ind&1)!=0) ops.add(s.charAt(ind));
            else nums.add((int)(s.charAt(ind)-'0'));
        }
        var twoAnswer = dfs(nums,ops,0,nums.size()-1);
        int res = 0;
        for (var answer:
             answers) {
            if(answer == trueAnswer) res += 5;
            else if(twoAnswer.contains(answer)) res += 2;
        }
        return res;
    }

    public HashSet<Integer> dfs(List<Integer> nums,List<Character> ops, int i, int j) {
        String key = i+"-"+j;
        if(hash.containsKey(key)) {
            return (HashSet<Integer>)hash.get(key);
        }
        var hashSet = new HashSet<Integer>();
        if(i == j) {
            hashSet.add(nums.get(i));
            hash.put(key,hashSet);
            return hashSet;
            //hash.put(key,new HashSet<Integer>(){{add(nums.get(i));}});
            //return (HashSet<Integer>)hash.get(key);
        }
        for(int ind=i;ind<j;ind++)
        {
            var nums1 = dfs(nums,ops,i,ind);
            var nums2 = dfs(nums,ops,ind+1,j);
            var op = ops.get(ind);
            for (int num1:nums1) {
                for (int num2:nums2) {
                    if(op=='+' && num1+num2<=1000) hashSet.add(num1+num2);
                    else if(op=='*' && num1*num2<=1000) hashSet.add(num1*num2);
                }
            }
            hash.put(key,hashSet);
        }
        return hashSet;
    }
}

Leetcode

posted @ 2021-09-29 08:11  Jamest  阅读(37)  评论(0编辑  收藏  举报