2022年02月LeetCode每日一题

2022-02-01
5分钟阅读时长

20220216 1719. 重构一棵树的方案数 困难

func checkWays(pairs [][]int) int {
    adj := map[int]map[int]bool{}
    for _, p := range pairs {
        x, y := p[0], p[1]
        if adj[x] == nil {
            adj[x] = map[int]bool{}
        }
        adj[x][y] = true
        if adj[y] == nil {
            adj[y] = map[int]bool{}
        }
        adj[y][x] = true
    }

    // 检测是否存在根节点
    root := -1
    for node, neighbours := range adj {
        if len(neighbours) == len(adj)-1 {
            root = node
            break
        }
    }
    if root == -1 {
        return 0
    }

    ans := 1
    for node, neighbours := range adj {
        if node == root {
            continue
        }

        currDegree := len(neighbours)
        parent := -1
        parentDegree := math.MaxInt32
        // 根据 degree 的大小找到 node 的父节点 parent
        for neighbour := range neighbours {
            if len(adj[neighbour]) < parentDegree && len(adj[neighbour]) >= currDegree {
                parent = neighbour
                parentDegree = len(adj[neighbour])
            }
        }
        if parent == -1 {
            return 0
        }
        // 检测 neighbours 是否为 adj[parent] 的子集
        for neighbour := range neighbours {
            if neighbour != parent && !adj[parent][neighbour] {
                return 0
            }
        }

        if parentDegree == currDegree {
            ans = 2
        }
    }
    return ans
}

20220217 688. 骑士在棋盘上的概率 中等

var dirs = []struct{ i, j int }{{-2, -1}, {-2, 1}, {2, -1}, {2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}}

func knightProbability(n, k, row, column int) float64 {
    dp := make([][][]float64, k+1)
    for step := range dp {
        dp[step] = make([][]float64, n)
        for i := 0; i < n; i++ {
            dp[step][i] = make([]float64, n)
            for j := 0; j < n; j++ {
                if step == 0 {
                    dp[step][i][j] = 1
                } else {
                    for _, d := range dirs {
                        if x, y := i+d.i, j+d.j; 0 <= x && x < n && 0 <= y && y < n {
                            dp[step][i][j] += dp[step-1][x][y] / 8
                        }
                    }
                }
            }
        }
    }
    return dp[k][row][column]
}

20220218 1791. 找出星型图的中心节点 简单

// 方法一:
func findCenter(edges [][]int) int {
    n := len(edges) + 1
    degrees := make([]int, n+1)
    for _, e := range edges {
        degrees[e[0]]++
        degrees[e[1]]++
    }
    for i, d := range degrees {
        if d == n-1 {
            return i
        }
    }
    return -1
}

// 方法二:
func findCenter(edges [][]int) int {
    if edges[0][0] == edges[1][0] || edges[0][0] == edges[1][1] {
        return edges[0][0]
    }
    return edges[0][1]
}

20220219 969. 煎饼排序 中等

func pancakeSort(arr []int) (ans []int) {
    for n := len(arr); n > 1; n-- {
        idx := 0
        for i, v := range arr[:n] {
            if v > arr[idx] { // 找最大值
                idx = i
            }
        }
        if idx == n - 1 {
            continue
        }
        // 1次翻转
        for i, m := 0, idx; i < (m+1)/2; i++ {
            arr[i], arr[m-i] = arr[m-i], arr[i]
        }
        // 2次翻转
        for i := 0; i < n/2; i++ {
            arr[i], arr[n-1-i] = arr[n-1-i], arr[i]
        }
        ans = append(ans, idx+1, n)
    }
    return ans
}

20220220 717. 1比特与2比特字符 简单

// 方法一:正序
func isOneBitCharacter(bits []int) bool {
    i, n := 0, len(bits)
    for i < n - 1 {
        i += bits[i] + 1
    }
    return i == n - 1
}
// 方法二:倒序
func isOneBitCharacter(bits []int) bool {
    n := len(bits)
    i := n - 2
    for i >= 0 && bits[i] == 1 {
        i--
    }
    return (n-i)%2 == 0
}

20220221 838. 推多米诺 中等

func pushDominoes(dominoes string) string {
    s := []byte(dominoes)
    i, n, left := 0, len(s), byte('L')
    for i < n {
        j := i
        for j < n && s[j] == '.' { // 找到一段连续的没有被推动的骨牌
            j++
        }
        right := byte('R')
        if j < n {
            right = s[j]
        }
        if left == right { // 方向相同,那么这些竖立骨牌也会倒向同一方向
            for i < j {
                s[i] = right
                i++
            }
        } else if left == 'R' && right == 'L' { // 方向相对,那么就从两侧向中间倒
            k := j - 1
            for i < k {
                s[i] = 'R'
                s[k] = 'L'
                i++
                k--
            }
        }
        left = right
        i = j + 1
    }
    return string(s)
}

20220222 1994. 好子集的数目 困难

var primes = []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}

func numberOfGoodSubsets(nums []int) (ans int) {
    const mod int = 1e9 + 7
    freq := [31]int{}
    for _, num := range nums {
        freq[num]++
    }

    f := make([]int, 1<<len(primes))
    f[0] = 1
    for i := 0; i < freq[1]; i++ {
        f[0] = f[0] * 2 % mod
    }
next:
    for i := 2; i < 31; i++ {
        if freq[i] == 0 {
            continue
        }

        // 检查 i 的每个质因数是否均不超过 1 个
        subset := 0
        for j, prime := range primes {
            if i%(prime*prime) == 0 {
                continue next
            }
            if i%prime == 0 {
                subset |= 1 << j
            }
        }

        // 动态规划
        for mask := 1 << len(primes); mask > 0; mask-- {
            if mask&subset == subset {
                f[mask] = (f[mask] + f[mask^subset]*freq[i]) % mod
            }
        }
    }

    for _, v := range f[1:] {
        ans = (ans + v) % mod
    }
    return
}

20220223 917. 仅仅反转字母 简单

func reverseOnlyLetters(s string) string {
    sb := []byte(s)
    l, r := 0, len(sb) - 1
    for l < r {
        for l < r && !unicode.IsLetter(rune(s[l]))  {
            l++
        }
        for l < r && !unicode.IsLetter(rune(s[r]))  {
            r--
        }
        sb[l], sb[r] = sb[r], sb[l]
        l++
        r--
    }
    return string(sb)
}

20220224 1706. 球会落何处 中等

func findBall(grid [][]int) []int {
    n := len(grid[0])
    ans := make([]int, n)
    for j := range ans {
        col := j // 球的初始列
        for _, row := range grid {
            dir := row[col]
            col += dir // 移动球
            if col < 0 || col == n || row[col] != dir { // 到达侧边或 V 形
                col = -1
                break
            }
        }
        ans[j] = col // col >= 0 为成功到达底部
    }
    return ans
}

20220227 553. 最优除法

func optimalDivision(nums []int) string {
    n := len(nums)
    if n == 1 {
        return strconv.Itoa(nums[0])
    }
    if n == 2 {
        return fmt.Sprintf("%d/%d", nums[0], nums[1])
    }
    ans := &strings.Builder{}
    ans.WriteString(fmt.Sprintf("%d/(%d", nums[0], nums[1]))
    for _, num := range nums[2:] {
        ans.WriteByte('/')
        ans.WriteString(strconv.Itoa(num))
    }
    ans.WriteByte(')')
    return ans.String()
}
下一页 LeetCode