挑战 - 每日系列(Algorithm + TypeChallenge)

47 阅读2分钟

算法小白,2024年2月21日,开始挑战在掘金发布“每日”系列。 (节假日可能会出门所以不算) 涉及到算法,type challenge 等,感兴趣的小伙伴可以持续关注督促互勉 🚀🚀🚀

算法

2867. 统计树中的合法路径数目

题意理解

根据给出的数据结构构造一棵树,统计树中合法的路径,路径中只有一个质数的被视为合法路径

思路

  • 实现一个方法用来判断输入参数是否是质数
  • 根据入参构造树结构
  • 遍历节点,跳过非质数节点
  • 对质数节点,遍历其相邻节点,过滤掉为质数的相邻节点
  • 统计不为质数的相邻节点...
  • 思路断了

挑战失败 ... 没想到怎么实现统计相邻节点,去除重复值

官方题解

const countPaths = (n, edges) => {
  // 构造图
  const graph = new Array(n + 1).fill("").map(() => [])

  for (const [i, j] of edges) {
    graph[i].push(j)
    graph[j].push(i)
  }

  // 递归判断相邻节点
  const dfs = (i, pre) => {
    seen.push(i)
    for (const j of graph[i]) {
      if (j !== pre && !isPrime(j)) {
        dfs(j, i)
      }
    }
  }

  let res = 0
  let seen = []
  let count = new Array(n + 1).fill(0)

  for (let i = 1; i <= n; i++) {
    if (!isPrime(i)) continue
    let cur = 0
    for (const j of graph[i]) {
      if (isPrime(j)) continue
      if (count[j] === 0) {
        seen = []
        dfs(j, 0)
        let cnt = seen.length
        for (const k of seen) {
          count[k] = cnt
        }
      }
      res += count[j] * cur
      cur += count[j]
    }
    res += cur
  }

  return res
}

// 是否是质数
const isPrime = (num) => {
  if (num < 2) return false
  for (let i = 2; i <= Math.sqrt(num); i++) {
    if (num % i === 0) return false
  }
  return true
}

TypeChallenge

实现类型 StringToUnion<S>,实现字符串类型的字母拆分成字母联合类型

type todo = 'abc'
type preview = StringToUnion<todo> // 'a' | 'b' | 'c'

思路

  • 类型推导 + 模板字符串 + 递归
  • 或者先拆分成元组类型,再元组转联合类型
type StringToUnion<S extends string> = S extends `${infer R}${infer L}`
  ? R | StringToUnion<L>
  : never
type StringToUnion<T extends string, R extends stirng[] = []> = 
  T extends `${infer S}${infer E}` 
    ? StringToUnion<E, [...R, S]>
    : R[number]