小李的伴学笔记7 | 豆包MarsCode AI刷题

44 阅读3分钟

473.疯狂整数的统计

问题描述

小C发现了一类特殊的整数,他称之为“疯狂整数”。疯狂整数是指只包含数字 '1' 和 '2' 的整数。举个例子,数字 12 和 121 都是疯狂整数。

现在,给定一个整数 N,你的任务是计算出所有小于或等于 N 的非负疯狂整数的数量。

解题思路

数据结构选择

由于我们需要生成所有可能的疯狂整数并检查它们是否小于或等于 N,我们可以使用一个队列(Queue)来辅助生成这些数字。队列可以帮助我们按顺序生成疯狂整数,并逐步检查它们是否满足条件。

算法步骤

  1. 初始化队列:将最小的两个疯狂整数 1 和 2 放入队列中。

  2. 遍历队列:从队列中取出数字,检查它是否小于或等于 N

    • 如果小于或等于 N,则计数器加一。
    • 生成新的疯狂整数:将当前数字乘以 10 并加上 1 或 2,得到新的疯狂整数。
    • 如果新生成的疯狂整数小于或等于 N,则将其加入队列。
  3. 重复步骤2,直到队列为空。

import java.util.LinkedList;
import java.util.Queue;

public class Main {
    public static int solution(int N) {
        Queue<Integer> queue = new LinkedList<>();
        queue.add(1);
        queue.add(2);
        int count = 0;
        while (!queue.isEmpty()) {
            int num = queue.poll();
            if (num <= N) {
                count++;
                int num1 = num * 10 + 1;
                int num2 = num * 10 + 2;
                if (num1 <= N) {
                    queue.add(num1);
                }
                if (num2 <= N) {
                    queue.add(num2);
                }
            }
        }
        return count;
    }

    public static void main(String[] args) {
        System.out.println(solution(21) == 5);
        System.out.println(solution(50) == 6);
        System.out.println(solution(5) == 2);
    }
}

359.可以移除的石头问题

问题描述

在一个二维平面上有若干块石头,每块石头位于某个整数坐标点上。每个坐标点上最多只能有一块石头。如果一块石头的同一行或同一列上存在其他石头,那么可以移除这块石头。

给定一个长度为 n 的数组 stones,其中 stones[i] = [xi, yi] 表示第 i 块石头的坐标。你的任务是计算可以移除的石头的最大数量。

解题思路

数据结构选择

为了解决这个问题,我们可以使用并查集(Union-Find)数据结构。并查集非常适合处理连通性问题,因为它可以高效地合并集合和查找元素所属的集合。

算法步骤

  1. 初始化并查集:为每个石头创建一个独立的集合。
  2. 合并操作:遍历所有石头,如果两个石头在同一行或同一列,则将它们所在的集合合并。
  3. 计算连通分量的数量:遍历所有石头,统计有多少个独立的连通分量。
  4. 计算可移除的石头数量:每个连通分量中至少保留一个石头,因此可以移除的石头数量为总石头数减去连通分量的数量。

代码

import java.util.*;

public class Main {
    public static int solution(int[][] stones) {
        // 初始化并查集
        int[] parent = new int[stones.length];
        for (int i = 0; i < stones.length; i++) {
            parent[i] = i;
        }

        // 合并同一行或同一列的石头
        Map<Integer, Integer> rowMap = new HashMap<>();
        Map<Integer, Integer> colMap = new HashMap<>();
        for (int i = 0; i < stones.length; i++) {
            int row = stones[i][0];
            int col = stones[i][1];
            if (rowMap.containsKey(row)) {
                union(parent, i, rowMap.get(row));
            } else {
                rowMap.put(row, i);
            }
            if (colMap.containsKey(col)) {
                union(parent, i, colMap.get(col));
            } else {
                colMap.put(col, i);
            }
        }

        // 计算连通分量的数量
        int componentCount = 0;
        for (int i = 0; i < stones.length; i++) {
            if (parent[i] == i) {
                componentCount++;
            }
        }

        // 每个连通分量中可以移除的石头数量
        return stones.length - componentCount;
    }

    // 并查集的查找操作
    private static int find(int[] parent, int i) {
        if (parent[i] != i) {
            parent[i] = find(parent, parent[i]);
        }
        return parent[i];
    }

    // 并查集的合并操作
    private static void union(int[] parent, int x, int y) {
        int rootX = find(parent, x);
        int rootY = find(parent, y);
        if (rootX != rootY) {
            parent[rootX] = rootY;
        }
    }

    public static void main(String[] args) {
        int[][] stones1 = {{0, 0}, {0, 1}, {1, 0}, {1, 2}, {2, 1}, {2, 2}, {3, 3}, {2, 3}};
        int[][] stones2 = {{0, 0}};
        int[][] stones3 = {{0, 1}, {1, 0}, {1, 1}};

        System.out.println(solution(stones1) == 7);
        System.out.println(solution(stones2) == 0);
        System.out.println(solution(stones3) == 2);
    }
}