目录
[1. 题目回顾](#1. 题目回顾)
[2. 思路分析](#2. 思路分析)
[三、DP2 跳台阶 ------ 动态规划最简模型](#三、DP2 跳台阶 —— 动态规划最简模型)
[1. 题目回顾](#1. 题目回顾)
[2. 思路分析](#2. 思路分析)
[3. 代码实现(Java版)](#3. 代码实现(Java版))
[4. 易错点](#4. 易错点)
[四、JZ61 扑克牌顺子 ------ 模拟与排序](#四、JZ61 扑克牌顺子 —— 模拟与排序)
[1. 题目回顾](#1. 题目回顾)
[2. 思路分析](#2. 思路分析)
[3. 代码实现](#3. 代码实现)
[4. 复杂度与优化](#4. 复杂度与优化)
[5. 边界场景](#5. 边界场景)
一、前言
-
BC146 添加逗号 (数字千分位格式化)添加逗号_牛客题霸_牛客网
-
DP2 跳台阶 (经典动态规划入门)跳台阶_牛客题霸_牛客网
-
JZ61 扑克牌顺子 (数组+模拟)扑克牌顺子_牛客题霸_牛客网
本文会从题目理解 、思路分析 、代码实现 、易错点四个维度展开,希望对正在刷题的你有帮助。
二、添加逗号
描述
1. 题目回顾
输入一个正整数 N(1 ≤ N ≤ 2×10⁹),将其转换为千分位格式:从最低位开始,每三位插入一个英文逗号。
示例:980364535 → 980,364,535
2. 思路分析
这道题考察的是字符串逆序处理 或数学取模。核心要点:
-
从个位开始,每三位一组
-
注意最高位组可能不足三位,不需要前导逗号
两种常见解法:
| 方法 | 思路 | 优缺点 |
|---|---|---|
| 字符串逆序 | 将数字转为字符串,逆序遍历,每3位插入逗号,再反转 | 直观,但注意反转的边界 |
| 数学取模 | 不断对1000取余,得到每组数字,存入栈或列表,最后拼接 | 适合大数,但N范围不大,两者均可 |
3.代码实现
字符串逆序
java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
StringBuffer str = new StringBuffer(in.nextLine());
int n = str.length();
if(n <= 3) {
System.out.println(str);
return;
}
str.reverse();
int left = 0, right = 0;
while(right < n) {
while(right < n && right - left < 3) {
right++;
}
if(right - left == 3) str.insert(right, ",");
left = right + 1;
}
System.out.println(str.reverse());
}
}
三、DP2 跳台阶 ------ 动态规划最简模型
1. 题目回顾
一只青蛙一次跳1级或2级,求跳上n级台阶有多少种不同跳法(顺序不同算不同结果)。
数据范围:0 ≤ n ≤ 40,要求 O(n) 时间,O(1) 空间。
示例:n=2 → 输出2(1+1 或 2)
2. 思路分析
这是斐波那契数列的变体。设 f(n) 表示跳上n级的方法数:
-
最后一步要么跳1级(来自n-1),要么跳2级(来自n-2)
-
状态转移:
f(n) = f(n-1) + f(n-2) -
初始条件:
f(0) = 1(0级一种方式,即不动),f(1) = 1
3. 代码实现(Java版)
java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] dp = new int[n + 1];
dp[0] = dp[1] = 1;
for(int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
System.out.println(dp[n]);
}
}
4. 易错点
-
n=0时,通常认为有1种跳法(不走也算一种),题目未明确但建议处理 -
空间复杂度 O(1) 要求不能开数组,用滚动变量即可
-
先后次序不同算不同结果,所以是排列而非组合,状态转移正确
四、JZ61 扑克牌顺子 ------ 模拟与排序
1. 题目回顾
从两副扑克中随机抽5张,判断是否为顺子:
-
A=1,J=11,Q=12,K=13(A不能作14)
-
大小王 = 0,可以当任意牌
-
数组长度5,元素范围0,13,最多4个0
示例:[6,0,2,0,4] → true(0可看作3和5,形成2~6)
2. 思路分析
核心思路:排序 + 统计0的数量 + 检查间隔
-
排序数组
-
统计0的个数
zero -
遍历非零部分:
-
若相邻相等 → 对子,直接false
-
否则累加间隔缺口
grap += (后 - 前 - 1)
-
-
如果
zero >= grap,可以用大小王补全缺口 → true
3. 代码实现
java
import java.util.*;
public class Solution {
public boolean IsContinuous (int[] numbers) {
// write code here
Arrays.sort(numbers);
int zero = 0;
int grap = 0;
for(int i = 0; i < numbers.length - 1; i++) {
if(numbers[i] == 0) zero++;
else {
if(numbers[i + 1] - numbers[i] == 0) return false;
else grap += numbers[i + 1] - numbers[i] - 1;
}
}
if(zero >= grap)
return true;
else
return false;
}
}
4. 复杂度与优化
-
排序后时间复杂度 O(n log n),满足要求
-
也可用哈希表 + 最大值最小值法达到 O(n):
-
遍历时排除0,记录最大最小值,检查是否有重复
-
若
max - min <= 4且无重复 → true(因为最多4个0)
-
5. 边界场景
-
[0,0,0,0,0]→ 可任意组成顺子,true -
[1,2,3,4,5]→ true -
[1,2,3,4,6]→ gap=1, zero=0 → false