• [Leetcode Weekly Contest]305


    链接:LeetCode

    [Leetcode]2367. 算术三元组的数目

    给你一个下标从 0 开始、严格递增 的整数数组 nums 和一个正整数 diff 。如果满足下述全部条件,则三元组 (i, j, k) 就是一个 算术三元组 :

    • i < j < k ,
    • nums[j] - nums[i] == diff 且
    • nums[k] - nums[j] == diff

    返回不同 算术三元组 的数目。

    由于是严格递增的,哈希即可。

    class Solution {
        public int arithmeticTriplets(int[] nums, int diff) {
            int res = 0;
            HashSet<Integer> set = new HashSet<>();
            for(var num:nums) set.add(num);
            for(var num:nums) {
                if(set.contains(num+diff) && set.contains(num+2*diff)) {
                    res ++;
                }
            }
            return res;
        }
    }
    

    [Leetcode]2368. 受限条件下可到达节点的数目

    现有一棵由 n 个节点组成的无向树,节点编号从 0 到 n - 1 ,共有 n - 1 条边。
    给你一个二维整数数组 edges ,长度为 n - 1 ,其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间存在一条边。另给你一个整数数组 restricted 表示 受限 节点。
    在不访问受限节点的前提下,返回你可以从节点 0 到达的 最多 节点数目。
    注意,节点 0 不 会标记为受限节点。

    BFS或DFS。构建全局双向图,从0开始,遍历全图。

    class Solution {
        public int reachableNodes(int n, int[][] edges, int[] restricted) {
            HashMap<Integer, HashSet<Integer>> hash = new HashMap<>();
            HashSet<Integer> restrictedSet = new HashSet<>();
            for(var re:restricted) restrictedSet.add(re);
            for(var edge:edges) {
                int i = edge[0], j = edge[1];
                if(!restrictedSet.contains(i) && !restrictedSet.contains(j)) {
                    hash.computeIfAbsent(i, key -> new HashSet<Integer>()).add(j);
                    hash.computeIfAbsent(j, key -> new HashSet<Integer>()).add(i);
                }
            }
            int res = 0;
            Deque<Integer> queue = new ArrayDeque<>();
            HashSet<Integer> visited = new HashSet<>();
            queue.addLast(0);
            while(!queue.isEmpty()) {
                int val = queue.pollFirst();
                visited.add(val);
                res++;
                for(int nxt:hash.getOrDefault(val, new HashSet<Integer>())) {
                    if(visited.contains(nxt)) continue;
                    queue.addLast(nxt);
                }
            }
            return res;
        }
    }
    

    [Leetcode]2369. 检查数组是否存在有效划分

    给你一个下标从 0 开始的整数数组 nums ,你必须将数组划分为一个或多个 连续 子数组。
    如果获得的这些子数组中每个都能满足下述条件 之一 ,则可以称其为数组的一种 有效 划分:

    1. 子数组 恰 由 2 个相等元素组成,例如,子数组 [2,2] 。
    2. 子数组 恰 由 3 个相等元素组成,例如,子数组 [4,4,4] 。
    3. 子数组 恰 由 3 个连续递增元素组成,并且相邻元素之间的差值为 1 。例如,子数组 [3,4,5] ,但是子数组 [1,3,5] 不符合要求。

    如果数组 至少 存在一种有效划分,返回 true ,否则,返回 false 。

    DP.
    定义 \(f[i+1]\) 表示从 \(\textit{nums}[0]\)\(\textit{nums}[i]\) 的这些元素能否有效划分。那么 \(f[0] = \texttt{true}\),答案为 \(f[n]\)

    根据题意,有

    \[f[i+1] = \text{OR} \begin{cases} f[i-1]\ \text{AND}\ \textit{nums}[i] = \textit{nums}[i-1],&i>0\\ f[i-2]\ \text{AND}\ \textit{nums}[i] = \textit{nums}[i-1] = \textit{nums}[i-2],&i>1\\ f[i-2]\ \text{AND}\ \textit{nums}[i] = \textit{nums}[i-1]+1 = \textit{nums}[i-2]+2,&i>1 \end{cases} \]

    class Solution {
        public boolean validPartition(int[] nums) {
            var n = nums.length;
            var f = new boolean[n + 1];
            f[0] = true;
            for (var i = 1; i < n; ++i)
                if (f[i - 1] && nums[i] == nums[i - 1] ||
                    i > 1 && f[i - 2] && (nums[i] == nums[i - 1] && nums[i] == nums[i - 2] ||
                                          nums[i] == nums[i - 1] + 1 && nums[i] == nums[i - 2] + 2))
                    f[i + 1] = true;
            return f[n];
        }
    }
    

    [Leetcode]2370. 最长理想子序列

    给你一个由小写字母组成的字符串 s ,和一个整数 k 。如果满足下述条件,则可以将字符串 t 视作是 理想字符串 :

    • t 是字符串 s 的一个子序列。
    • t 中每两个 相邻 字母在字母表中位次的绝对差值小于或等于 k 。

    返回 最长 理想字符串的长度。
    字符串的子序列同样是一个字符串,并且子序列还满足:可以经由其他字符串删除某些字符(也可以不删除)但不改变剩余字符的顺序得到。
    注意:字母表顺序不会循环。例如,'a' 和 'z' 在字母表中位次的绝对差值是 25 ,而不是 1 。

    子序列 DP + 枚举字符 + 空间优化.看到子序列和相邻就可以往 DP 上想。

    class Solution {
        public int longestIdealString(String s, int k) {
            int n = s.length();
            int[] index = new int[26];
            Arrays.fill(index, -1);
            int[] dp = new int[n];
            Arrays.fill(dp, 1);
            for(int i=0;i<n;++i) {
                char ch = s.charAt(i);
                int idx = ch - 'a';
                if(i == 0) {
                    index[idx] = i;
                    dp[i] = 1;
                } else {
                    for(int j = Math.max(idx-k, 0); j < Math.min(idx+k+1, 26); ++j) {
                        if(index[j] == -1) continue;
                        else dp[i] = Math.max(dp[i], dp[index[j]] + 1);
                    }
                    index[idx] = i;
                }
            }
            return Arrays.stream(dp).max().getAsInt();
        }
    }
    

    参考:LeetCode

  • 相关阅读:
    懂一点Python系列——快速入门
    DatagridView 控件列顺序与设置的不一样
    WinForm Column cannot be added because its CellType property is null.
    Rabbitmq消息服务器通讯异常: name must not be blank
    Redis 数据库
    redis 安装与使用
    windows 服务的安装与卸载之bat脚本命令
    以超级管理员方式运行bat文件
    CMD 下切换目录
    C#导出Excel后关闭进程EXCEL.EXE
  • 原文地址:https://www.cnblogs.com/hellojamest/p/16563524.html
Copyright © 2020-2023  润新知