473.疯狂整数的统计
问题描述
小C发现了一类特殊的整数,他称之为“疯狂整数”。疯狂整数是指只包含数字 '1' 和 '2' 的整数。举个例子,数字 1、2 和 121 都是疯狂整数。
现在,给定一个整数 N,你的任务是计算出所有小于或等于 N 的非负疯狂整数的数量。
解题思路
数据结构选择
由于我们需要生成所有可能的疯狂整数并检查它们是否小于或等于 N,我们可以使用一个队列(Queue)来辅助生成这些数字。队列可以帮助我们按顺序生成疯狂整数,并逐步检查它们是否满足条件。
算法步骤
-
初始化队列:将最小的两个疯狂整数
1和2放入队列中。 -
遍历队列:从队列中取出数字,检查它是否小于或等于
N。- 如果小于或等于
N,则计数器加一。 - 生成新的疯狂整数:将当前数字乘以
10并加上1或2,得到新的疯狂整数。 - 如果新生成的疯狂整数小于或等于
N,则将其加入队列。
- 如果小于或等于
-
重复步骤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)数据结构。并查集非常适合处理连通性问题,因为它可以高效地合并集合和查找元素所属的集合。
算法步骤
- 初始化并查集:为每个石头创建一个独立的集合。
- 合并操作:遍历所有石头,如果两个石头在同一行或同一列,则将它们所在的集合合并。
- 计算连通分量的数量:遍历所有石头,统计有多少个独立的连通分量。
- 计算可移除的石头数量:每个连通分量中至少保留一个石头,因此可以移除的石头数量为总石头数减去连通分量的数量。
代码
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);
}
}