[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

posted @ 2022-08-08 21:26  Jamest  阅读(48)  评论(0编辑  收藏  举报