当前位置: 首页 > news >正文

【Java +AI |基础篇day3 流程控制】

改进了一下格式 内容分两部分 第一部分是黑马教学的简单内容sh适合新学的看👀 后一部分是上了点难度 和 加了一些实用技巧

go go go !!!


一、核心概述

程序流程控制是控制代码执行顺序的核心技术,主要分为三大结构:顺序结构(自上而下默认执行)、分支结构(按条件选执行路径)、循环结构(重复执行指定代码),配合break/continue辅助控制,支撑各类复杂业务逻辑实现。

二、分支结构(条件选择执行)

1. if 分支(灵活判断,支持区间 / 多条件)

(1)三种核心形式
形式格式适用场景
单条件判断if (条件表达式) { 语句体; }满足条件才执行某段代码
二选一判断if (条件表达式) { 语句体1; } else { 语句体2; }两种互斥场景选择(如登录成功 / 失败)
多条件区间判断if (条件1) { 语句体1; } else if (条件2) { 语句体2; } ... else { 语句体n; }多区间 / 多场景判断(如 BMI 等级、温度穿衣建议)
(2)关键注意事项
  • 条件表达式结果必须为boolean类型(true/false);

  • if (条件)后不能加;,否则语句体将不受条件控制;

  • 若语句体仅一行代码,大括号可省略(建议保留,提升可读性)。

2. switch 分支(等值判断,格式优雅)

(1)核心格式与执行流程

java

switch(表达式) {case 值1: 语句体1; break;case 值2: 语句体2; break;...default: 语句体n; // 所有case不匹配时执行
}
  • 执行流程:计算表达式值 → 匹配 case 值 → 执行对应语句体 → 遇break跳出分支(无break则穿透)。

(2)关键限制与注意事项
  • 表达式类型支持:byteshortintchar(JDK5 + 支持枚举,JDK7 + 支持 String),不支持doublefloatlong

  • case 值必须是字面量(不能是变量),且不可重复;

  • 穿透性应用:多个 case 逻辑相同时,可省略部分break,让代码穿透到目标 case 执行(简化重复代码)。

(3)if 与 switch 对比
特性if 分支switch 分支
判断逻辑支持区间、多条件组合(灵活)仅支持等值判断(单一)
代码风格适合复杂条件,逻辑直观适合多等值场景,格式简洁、性能优
适用场景BMI 等级、温度区间、多条件校验菜单选择、角色权限匹配、状态判断

三、循环结构(重复执行代码)

1. for 循环(已知循环次数,推荐首选)

(1)格式与执行流程

java

for (初始化语句; 循环条件; 迭代语句) {循环体语句; // 重复执行的代码
}

for each ,for(:){ } 熟悉了解一下 jdk8 的stream流

  • 执行流程:初始化语句(仅执行 1 次)→ 判断循环条件(true则执行循环体)→ 执行迭代语句 → 重复判断条件,直至false结束。

(2)典型应用场景
  • 固定次数循环(如输出 10 次 HelloWorld、1-100 求和);

  • 遍历已知范围数据(如水仙花数查找、奇数和计算)。

2. while 循环(未知循环次数,灵活控制)

(1)格式与执行流程

java

初始化语句;
while (循环条件) {循环体语句;迭代语句;
}
  • 执行流程:初始化 → 判断条件(true执行循环体 + 迭代)→ 重复判断,直至false结束(先判断后执行)。

(2)典型应用场景
  • 未知循环次数的场景(如纸张折叠到珠峰高度、复利翻倍计算);

  • 依赖外部条件终止的循环(如用户输入指定值退出)。

3. do-while 循环(先执行后判断,至少执行 1 次)

(1)格式与特点

java

初始化语句;
do {循环体语句;迭代语句;
} while (循环条件);
  • 核心特点:先执行 1 次循环体,再判断条件(确保循环至少执行 1 次);

  • 适用场景:必须执行 1 次的操作(如 12306 刷票、用户登录验证)。

4. 三种循环对比与选择

循环类型核心特点适用场景变量作用域
for已知循环次数,结构紧凑固定次数循环、范围遍历循环变量仅在循环内有效
while未知循环次数,先判断后执行外部条件控制的循环循环变量在循环外可复用
do-while未知循环次数,先执行后判断必须执行 1 次的操作循环变量在循环外可复用
  • 功能等价性:三种循环可相互替代,优先按 “已知次数用 for,未知次数用 while,必须执行 1 次用 do-while” 选择。

5. 循环进阶用法

(1)死循环(无限执行,需手动终止)
  • 常见写法:

    java

    for (;;) { ... } // 经典写法
    while (true) { ... } // 最常用
    do { ... } while (true);

  • 应用场景:服务器监听、游戏主循环、用户交互菜单(需配合break终止)。

(2)循环嵌套(循环内包含循环)
  • 核心特点:外循环每执行 1 次,内循环完整执行 1 轮

  • 典型应用:打印图形(如矩形、三角形)、多层数据遍历(如表格数据)。

四、循环控制符(break/continue)

1. break(终止当前循环 /switch)

  • 作用:跳出当前所在的循环(for/while/do-while)或 switch 分支;

  • 注意:仅终止 “当前层级” 的循环,嵌套循环中不影响外层循环。

2. continue(跳过当前次,进入下一次)

  • 作用:跳过循环体中剩余代码,直接执行下一次迭代(不终止循环);

  • 注意:仅在循环中使用,不能用于 switch 分支。

3. 用法示例

java

// break:找到100以内第一个能被7整除的数,终止循环
for (int i = 1; i <= 100; i++) {if (i % 7 == 0) {System.out.println("第一个能被7整除的数:" + i);break; // 终止for循环}
}
​
// continue:打印1-10中的奇数(跳过偶数)
for (int i = 1; i <= 10; i++) {if (i % 2 == 0) {continue; // 跳过偶数,直接进入下一次循环}System.out.println(i);
}

五、综合实战案例(知识点整合)

1. 猜数字游戏(循环 + 分支 + 随机数)

  • 核心逻辑:生成 1-100 随机数 → 死循环接收用户猜测 → 分支判断大小 → 猜中用break终止。

  • 关键技术:Random生成随机数(导包→创建对象→nextInt(n)生成 0~n-1)。

2. 验证码生成(循环 + switch + 随机数)

  • 核心逻辑:指定验证码长度(如 5 位)→ 循环生成每位字符(数字 / 大写字母 / 小写字母随机切换)→ 字符串拼接结果。

  • 关键技巧:用nextInt(3)随机选择字符类型,配合 ASCII 码生成字母(A=65,a=97)。

3. 找素数(循环嵌套 + 分支)

  • 需求:判断 101-200 之间的素数(仅能被 1 和自身整除)。

  • 核心逻辑:外层循环遍历 101-200 → 内层循环判断是否能被 2~√n 整除 → 无整除则为素数。

4. 简单计算器(分支 + 输入输出)

  • 核心逻辑:接收用户输入的两个数字和运算符 → switch 判断运算符 → 执行对应运算并输出结果。

六、核心避坑指南

  1. 分支结构:if 条件表达式必须是boolean类型,避免用=代替==;switch 的 case 必须加break(除非需要穿透)。

  2. 循环结构:避免遗漏迭代语句(导致死循环);for 循环的初始化语句不能声明重复变量;while/do-while 需确保循环条件能终止。

  3. 循环控制符:break 仅终止当前层级循环,嵌套循环需注意终止范围;continue 不能用于循环体外。

  4. 随机数:Random.nextInt(n)生成 0~n-1 的数,生成指定范围(如 65-91)需用 “nextInt(范围长度) + 起始值”。


以下是在原有笔记基础上拓展的更深入、更实用的 Java 程序流程控制学习内容,补充了底层逻辑、实战技巧与真实场景应用:

二、分支结构(条件选择执行)补充

1. if 分支:深入技巧与场景拓展

(1)条件表达式的 “短路逻辑” 优化

if 的条件表达式支持&&(短路与)和||(短路或),利用其 “短路特性” 可提升效率并避免异常:

  • &&:左侧为false时,右侧表达式不执行(如if (obj != null && obj.getValue() > 0),先判断非空避免空指针);

  • ||:左侧为true时,右侧表达式不执行(如if (isAdmin || hasPermission()),管理员直接通过,无需检查权限)。

反例:若写成if (obj.getValue() > 0 && obj != null),当objnull时会直接抛出NullPointerException

(2)复杂条件的 “可读性重构”

多条件判断时,避免冗长的if-else if链,可通过 “变量提取” 或 “策略模式” 优化:

java

// 原始:冗长且难维护
if (score >= 90 && score <= 100) {grade = "优秀";
} else if (score >= 80 && score < 90) {grade = "良好";
} 
// ... 更多条件
​
// 优化:提取条件变量,逻辑更清晰
boolean isExcellent = score >= 90 && score <= 100;
boolean isGood = score >= 80 && score < 90;
if (isExcellent) { ... } else if (isGood) { ... }

真实场景:电商订单状态判断(待支付、已支付、已发货等),通过提取isPaid()isShipped()等方法,让分支逻辑更直观。

2. switch 分支:JDK 新特性与高级用法

(1)JDK 12+ 增强 switch(箭头语法与 yield)

传统 switch 需要break避免穿透,JDK12 引入箭头语法->)自动终止,且支持yield返回值

java

运行

// 增强版:简洁且无穿透问题
int day = 3;
String week = switch (day) {case 1 -> "周一";case 2 -> "周二";case 3 -> "周三";default -> "未知"; // 无需break,自动跳出
};
​
// 带逻辑块的yield返回
int num = 2;
String result = switch (num) {case 1 -> {System.out.println("处理1");yield "one"; // 返回值}case 2 -> {System.out.println("处理2");yield "two";}default -> "other";
};

优势:减少break遗漏导致的逻辑错误,支持直接返回值,更适合作为 “表达式” 使用(如赋值、参数传递)。

(2)穿透性的合理应用(而非禁用)

穿透性并非缺陷,在 “多值对应同一逻辑” 场景下可简化代码:

java

// 示例:判断季节(3-5春,6-8夏,9-11秋,12-2冬)
int month = 4;
String season = switch (month) {case 3,4,5 -> "春季"; // 多case合并(JDK14+)case 6,7,8 -> "夏季";case 9,10,11 -> "秋季";case 12,1,2 -> "冬季";default -> "无效月份";
};

注意:传统写法中,若需穿透,需显式去掉break,但需注释说明(避免他人误改):

java

case 12:
case 1:
case 2: season = "冬季"; break; // 最后一个case加break
(3)switch vs if 的性能差异
  • switch:编译时会将case值转换为 “跳转表”(类似数组索引),匹配时直接定位,O (1) 时间复杂度,适合多等值判断(如 10 + 个 case);

  • if-else

    :按顺序逐个判断,

    O (n) 时间复杂度

    ,适合少量条件或区间判断。

    场景选择

    :角色权限判断(10 + 种角色)用 switch,而年龄区间判断(如儿童 / 青年 / 中年)用 if 更合适。

三、循环结构(重复执行代码)补充

1. for 循环:高级用法与性能细节

(1)增强 for 循环(foreach)的底层与限制

用于遍历数组或集合,语法简洁,但不支持修改元素(值传递)无法获取索引

java

int[] arr = {1,2,3};
for (int num : arr) { num *= 2; // 无效!仅修改临时变量,原数组不变
}
// 原数组仍为 {1,2,3}

适用场景:仅需读取元素(如打印集合内容),无需修改或索引;若需修改,仍用普通 for 循环。

(2)循环变量的作用域陷阱

for 循环的初始化语句中声明的变量,仅在循环内有效,避免重复声明导致编译错误:

java

for (int i = 0; i < 5; i++) { ... }
// System.out.println(i); // 编译报错:i未定义
​
// 正确:若需循环外使用变量,在外部声明
int i;
for (i = 0; i < 5; i++) { ... }
System.out.println(i); // 输出5(循环结束后的值)

2. 循环嵌套:效率优化核心技巧

嵌套循环的时间复杂度是外层次数 × 内层次数,优化核心是减少内层循环的执行次数

反例:双层循环求 1-100 的素数,内层循环从 2 遍历到 n-1

java

for (int n = 101; n <= 200; n++) {boolean isPrime = true;for (int i = 2; i < n; i++) { // 低效:i无需到n-1if (n % i == 0) {isPrime = false;break;}}
}

优化:内层循环仅需到√n(若 n 有因子,必有一个≤√n),且跳过偶数

java

for (int n = 101; n <= 200; n += 2) { // 跳过偶数(除2外偶数都不是素数)boolean isPrime = true;for (int i = 3; i <= Math.sqrt(n); i += 2) { // 仅判断奇数因子if (n % i == 0) {isPrime = false;break;}}
}

效果:外层循环次数减少一半,内层循环次数减少至√n/2,效率大幅提升。

3. 死循环的 “安全退出” 机制

死循环需配合break手动终止,实际开发中需避免 “无法退出” 的风险,常用策略:

  • 计数器限制:防止无限执行(如最多尝试 3 次);

  • 超时控制:超过指定时间强制退出(需结合时间戳)。

java

// 示例:用户登录(最多3次机会)
int maxAttempts = 3;
int attempts = 0;
while (true) {if (attempts >= maxAttempts) {System.out.println("超过最大尝试次数,退出");break;}// 输入密码并验证if (isValidPassword(input)) {System.out.println("登录成功");break;}attempts++;
}

四、循环控制符(break/continue)补充

1. 带标签的 break/continue(嵌套循环专用)

默认break/continue仅作用于当前循环,带标签(label:)可控制外层循环:

java

// 示例:找到二维数组中第一个偶数,终止所有循环
int[][] matrix = {{1,3,5}, {2,4,6}, {7,8,9}};
outer: // 外层循环标签
for (int i = 0; i < matrix.length; i++) {for (int j = 0; j < matrix[i].length; j++) {if (matrix[i][j] % 2 == 0) {System.out.println("找到偶数:" + matrix[i][j]);break outer; // 终止外层循环}}
}

注意:标签名需与循环绑定,且仅建议在两层嵌套中使用(多层嵌套易导致代码混乱)。

2. continue 在不同循环中的差异

  • for 循环continue后会自动执行 “迭代语句”(如i++);

  • while 循环continue后需手动执行迭代(否则可能死循环)。

java

运行

// for循环:continue后自动i++
for (int i = 0; i < 3; i++) {if (i == 1) continue;System.out.println(i); // 输出0、2
}
​
// while循环:需手动迭代,否则i=1时会无限循环
int i = 0;
while (i < 3) {if (i == 1) {i++; // 必须手动i++,否则continue后i始终为1continue;}System.out.println(i);i++;
}

五、综合实战案例:深度优化与场景细节

1. 猜数字游戏(升级版)

核心优化:限制猜测次数、显示已猜次数、提示最近两次猜测的偏差趋势。

java

import java.util.Random;
import java.util.Scanner;
​
public class GuessNumber {public static void main(String[] args) {Random random = new Random();int target = random.nextInt(100) + 1; // 1-100Scanner sc = new Scanner(System.in);int maxTries = 7;int tries = 0;int lastDiff = 0; // 记录上一次的差值
​while (tries < maxTries) {tries++;System.out.printf("第%d次猜测(1-100):", tries);int guess = sc.nextInt();
​if (guess == target) {System.out.println("恭喜猜对!用了" + tries + "次");break;}
​int currentDiff = Math.abs(guess - target);if (tries > 1) {// 提示趋势(更近/更远)if (currentDiff < lastDiff) {System.out.println("比上一次更接近了!");} else {System.out.println("比上一次更远了!");}}
​System.out.println(guess > target ? "猜大了" : "猜小了");lastDiff = currentDiff;}
​if (tries >= maxTries) {System.out.println("次数用尽,答案是:" + target);}sc.close();}
}

2. 验证码生成(防混淆版)

核心优化:排除易混淆字符(0 与 O、1 与 l、I),确保可读性。

java

import java.util.Random;
​
public class CaptchaGenerator {public static String generate(int length) {// 可用字符:排除0,O,1,l,IString digits = "23456789";String upper = "ABCDEFGHJKLMNPQRSTUVWXYZ"; // 无OString lower = "abcdefghjkmnpqrstuvwxyz"; // 无lString all = digits + upper + lower;
​Random random = new Random();StringBuilder sb = new StringBuilder();for (int i = 0; i < length; i++) {int index = random.nextInt(all.length());sb.append(all.charAt(index));}return sb.toString();}
​public static void main(String[] args) {System.out.println("验证码:" + generate(6)); // 如:K3f7Q2}
}

六、避坑指南(新增高频问题)

  1. if-else 的 “悬挂 else” 问题

    省略大括号时,else 默认匹配最近的 if,易导致逻辑错误:

    java

    // 错误示例:else实际匹配内层if,而非外层
    if (a > 0)if (b > 0)System.out.println("both >0");
    else // 实际属于内层if的elseSystem.out.println("a <=0");
    ​
    // 正确:加括号明确层级
    if (a > 0) {if (b > 0) {System.out.println("both >0");}
    } else {System.out.println("a <=0");
    }

  2. switch 的 case 值类型错误

    若表达式为long,即使 case 值是 int 也会编译失败(long 范围大于 int,无法隐式转换):

    java

    long num = 10;
    switch (num) {// case 10: ... 编译报错:不支持long类型
    }

  3. 循环中修改循环变量导致逻辑混乱

    避免在循环体中随意修改循环变量(如 for 循环中手动i++):

    java

    // 易错:循环体中i++导致跳过元素
    for (int i = 0; i < 5; i++) {System.out.println(i);i++; // 实际i每次+2,输出0、2、4
    }

通过以上补充,不仅深化了基础语法的理解,更结合实际开发场景提供了可直接复用的技巧与避坑方案,帮助在复杂业务逻辑中更高效地使用流程控制。

补充的知识点也不能 初学者也可以看 建议初学者把黑马的示例代码都自己手敲✊一遍

然后在洛谷教育上 把相关章节的题目都做一遍 ✅✅✅ 训练自己的coding能力


Java 程序流程控制 5 道深度面试题(含场景 + 答案)

面试题 1(分支结构深度对比)

场景

面试官:“以下两段代码分别用 if 和 switch 实现相同的业务逻辑(根据会员等级发放优惠券),请分析运行结果并解释原因,同时说明 switch 穿透性的适用场景和风险,以及 if 和 switch 在底层执行效率上的差异。”

java

// 代码1:if分支实现
public class MemberDemo1 {public static void main(String[] args) {String memberLevel = "VIP2";int coupon = 0;if ("VIP1".equals(memberLevel)) {coupon = 10;} else if ("VIP2".equals(memberLevel)) {coupon = 20;} else if ("VIP3".equals(memberLevel)) {coupon = 50;} else {coupon = 5;}System.out.println("if分支优惠券:" + coupon);}
}
​
// 代码2:switch分支实现(故意遗漏部分break)
public class MemberDemo2 {public static void main(String[] args) {String memberLevel = "VIP2";int coupon = 0;switch (memberLevel) {case "VIP1":coupon = 10;case "VIP2":coupon += 20;case "VIP3":coupon += 30;break;default:coupon = 5;}System.out.println("switch分支优惠券:" + coupon);}
}

问题

  1. 两段代码的运行结果分别是什么?

  2. 代码 2 中 switch 分支的执行流程是什么?switch 穿透性的适用场景和潜在风险是什么?

  3. if 和 switch 在底层执行效率上有何差异?分别适合什么业务场景?


面试题 2(循环嵌套 + break/continue 控制)

场景

面试官:“以下代码是一个嵌套循环案例,用于查找 100-200 之间的所有‘双素数对’(两个连续奇数均为素数,如 3 和 5、5 和 7),代码中存在逻辑错误导致结果异常,请找出错误并修复,同时解释 break 和 continue 在嵌套循环中的作用范围,以及如何实现‘终止外层循环’。”

java

运行

public class TwinPrimeDemo {public static void main(String[] args) {System.out.println("100-200之间的双素数对:");for (int i = 101; i <= 199; i += 2) {int j = i + 2;if (isPrime(i) && isPrime(j)) {System.out.println(i + "和" + j);continue;}break;}}
​// 判断是否为素数(仅能被1和自身整除)private static boolean isPrime(int num) {if (num < 2) return false;for (int k = 2; k < num; k++) {if (num % k == 0) {continue;}}return true;}
}

问题

  1. 代码中存在哪些逻辑错误?请逐一指出并说明原因。

  2. 修复后的完整代码是什么?

  3. break 和 continue 在嵌套循环中默认作用于哪一层?如何实现 “终止外层循环”(举例说明)?


面试题 3(综合循环 + 分支 + 随机数:抽奖系统)

场景

面试官:“请设计一个抽奖系统,满足以下需求,考察你对循环、分支、随机数的综合运用能力:”

需求

  1. 奖项设置:一等奖(10% 概率)、二等奖(20% 概率)、三等奖(30% 概率)、谢谢参与(40% 概率);

  2. 每个用户每天最多抽奖 3 次,抽奖次数耗尽后提示 “今日抽奖次数已用完”;

  3. 抽中一等奖后直接终止当日抽奖(不再允许后续抽奖);

  4. 输出每次抽奖结果和剩余次数。

问题

  1. 编写完整的抽奖系统代码(使用 Scanner 接收用户输入,Random 生成随机数)。

  2. 代码中如何控制抽奖概率?核心逻辑是什么?

  3. 如何确保抽中一等奖后终止当日抽奖?用到了哪些流程控制技术?


面试题 4(死循环 + 条件终止:用户交互菜单)

场景

面试官:“以下是一个简化的用户交互菜单代码,用于实现‘学生信息管理系统’的主菜单,但存在循环终止逻辑错误和用户输入异常问题,请修复代码并解释死循环的实际应用场景,以及如何优雅地终止死循环。”

java

运行

import java.util.Scanner;
​
public class StudentMenuDemo {public static void main(String[] args) {Scanner sc = new Scanner(System.in);while (true) {System.out.println("=== 学生信息管理系统 ===");System.out.println("1. 查看学生信息");System.out.println("2. 添加学生信息");System.out.println("3. 退出系统");System.out.print("请选择功能(1-3):");int choice = sc.nextInt();if (choice == 1) {System.out.println("查看学生信息...");} else if (choice == 2) {System.out.println("添加学生信息...");} else if (choice == 3) {System.out.println("退出系统...");} else {System.out.println("输入错误,请重新选择!");}}}
}

问题

  1. 代码中存在哪些问题?请指出并修复。

  2. 死循环的实际应用场景有哪些?除了while (true),还有哪些死循环写法?

  3. 终止死循环的常见方式有哪些?本案例中最适合用哪种方式?为什么?


面试题 5(算法优化:素数判断的循环效率)

场景

面试官:“素数判断是循环结构的经典应用,以下代码用于统计 1-10000 之间的素数个数,但循环效率较低,请分析低效原因并优化代码,同时解释优化思路和数学原理。”

java

运行

public class PrimeCountDemo {public static void main(String[] args) {int count = 0;for (int i = 2; i <= 10000; i++) {if (isPrime(i)) {count++;}}System.out.println("1-10000之间的素数个数:" + count);}private static boolean isPrime(int num) {for (int j = 2; j < num; j++) {if (num % j == 0) {return false;}}return true;}
}

问题

  1. 原代码的低效原因是什么?时间复杂度是多少?

  2. 优化后的代码是什么?优化思路和数学原理是什么?

  3. 进一步优化(如筛选法)的核心逻辑是什么?请简要描述实现步骤。


参考答案

面试题 1 参考答案

1. 运行结果

  • 代码 1(if 分支):if分支优惠券:20

  • 代码 2(switch 分支):switch分支优惠券:50

2. switch 执行流程与穿透性分析

  • 代码 2 执行流程:

    1. memberLevel="VIP2",匹配case "VIP2"

    2. 执行coupon +=20(coupon=20);

    3. break,触发穿透,执行case "VIP3"coupon +=30(coupon=50);

    4. break,跳出 switch 分支,最终输出 50。

  • 穿透性适用场景:多个 case 逻辑相同时(如周一至周三执行相同代码),可省略中间 case 的break,简化代码;

  • 潜在风险:忘记加break导致逻辑穿透,出现非预期结果(如本案例误加 30 优惠券)。

3. if 与 switch 效率差异与场景选择

  • 效率差异:

    • switch:底层通过 “跳转表” 实现,等值匹配时直接定位 case,效率高于 if(尤其 case 数量多时);

    • if:需依次判断条件,适合少量条件或区间判断,数量越多效率越低。

  • 场景选择:

    • if:区间判断(如 BMI 等级、温度范围)、多条件组合(如age>18 && score>=60);

    • switch:等值判断(如菜单选择、会员等级、状态码匹配),代码更简洁优雅。

面试题 2 参考答案

1. 存在的逻辑错误

  • 错误 1:外层循环中break位置错误,导致仅判断第一个数(101 和 103)后就终止循环,无法遍历所有数;

  • 错误 2:isPrime方法中continue使用错误,应改为return false(当前数能被整除,直接判定为非素数),原代码会继续循环,最终误判非素数为素数;

  • 错误 3:isPrime方法中循环条件k < num效率低,可优化为k <= Math.sqrt(num)(大于根号 num 的因数无需判断)。

2. 修复后的完整代码

java

运行

public class TwinPrimeDemo {public static void main(String[] args) {System.out.println("100-200之间的双素数对:");for (int i = 101; i <= 199; i += 2) {int j = i + 2;if (isPrime(i) && isPrime(j)) {System.out.println(i + "和" + j);}// 移除错误的break,确保遍历所有奇数}}private static boolean isPrime(int num) {if (num < 2) return false;// 优化循环条件:仅判断到根号num,减少循环次数for (int k = 2; k <= Math.sqrt(num); k++) {if (num % k == 0) {return false; // 能被整除,非素数}}return true;}
}

3. break/continue 作用范围与外层循环终止

  • 默认作用范围:break 和 continue 仅作用于 “当前所在的最内层循环”;

  • 终止外层循环的方式:使用 “标签(label)”,示例:

    java

    运行

    outer: for (int i = 0; i < 5; i++) { // 外层循环标签outerfor (int j = 0; j < 3; j++) {if (j == 1) {break outer; // 终止外层循环}System.out.println(i + "," + j);}
    }

面试题 3 参考答案

1. 完整抽奖系统代码

java

运行

import java.util.Random;
import java.util.Scanner;public class LotterySystem {public static void main(String[] args) {Scanner sc = new Scanner(System.in);Random random = new Random();int maxTimes = 3; // 每日最大抽奖次数int remainingTimes = maxTimes; // 剩余次数while (remainingTimes > 0) {System.out.print("是否参与抽奖(y/n):");String choice = sc.next();if (!"y".equalsIgnoreCase(choice)) {System.out.println("已取消抽奖,今日剩余次数:" + remainingTimes);continue;}// 生成0-99的随机数,控制概率int randomNum = random.nextInt(100);String award = "";boolean isFirstAward = false;// 概率判断:0-9(10%)一等奖,10-29(20%)二等奖,30-59(30%)三等奖,60-99(40%)谢谢参与if (randomNum < 10) {award = "一等奖(10元优惠券)";isFirstAward = true;} else if (randomNum < 30) {award = "二等奖(5元优惠券)";} else if (randomNum < 60) {award = "三等奖(2元优惠券)";} else {award = "谢谢参与";}// 输出结果remainingTimes--;System.out.println("抽奖结果:" + award + ",今日剩余次数:" + remainingTimes);// 抽中一等奖,终止当日抽奖if (isFirstAward) {System.out.println("恭喜抽中一等奖,今日抽奖结束!");break;}}if (remainingTimes == 0) {System.out.println("今日抽奖次数已用完,明日再来!");}sc.close();}
}

2. 概率控制核心逻辑

  • 利用Random.nextInt(100)生成 0-99 的随机数(共 100 个可能值);

  • 按概率分配区间:一等奖占 10 个值(0-9)、二等奖占 20 个值(10-29)、三等奖占 30 个值(30-59)、谢谢参与占 40 个值(60-99);

  • 核心原理:随机数在每个区间的分布概率与区间长度成正比,实现指定概率控制。

3. 一等奖终止逻辑

  • 定义isFirstAward布尔变量,标记是否抽中一等奖;

  • 抽中后设置isFirstAward=true,执行break终止死循环(while (remainingTimes > 0)),实现当日抽奖终止;

  • 用到的流程控制技术:break终止循环、布尔变量标记状态、while循环控制抽奖次数。

面试题 4 参考答案

1. 代码问题与修复

  • 存在问题:

    1. 选择 “3. 退出系统” 时无终止循环逻辑,导致死循环无法退出;

    2. 若用户输入非整数(如字母、符号),调用sc.nextInt()会抛出InputMismatchException,程序崩溃。

  • 修复后的代码:

    java

    运行

    import java.util.Scanner;public class StudentMenuDemo {public static void main(String[] args) {Scanner sc = new Scanner(System.in);while (true) {System.out.println("=== 学生信息管理系统 ===");System.out.println("1. 查看学生信息");System.out.println("2. 添加学生信息");System.out.println("3. 退出系统");System.out.print("请选择功能(1-3):");// 处理非整数输入if (!sc.hasNextInt()) {System.out.println("输入错误,请输入1-3的整数!");sc.next(); // 清空无效输入continue;}int choice = sc.nextInt();if (choice == 1) {System.out.println("查看学生信息...");} else if (choice == 2) {System.out.println("添加学生信息...");} else if (choice == 3) {System.out.println("退出系统...");break; // 终止死循环} else {System.out.println("输入错误,请重新选择!");}}sc.close();}
    }

2. 死循环应用场景与写法

  • 应用场景:服务器监听、用户交互菜单、游戏主循环、消息队列消费等(需要持续运行的业务);

  • 常见写法:

    java

    运行

    for (;;) { ... } // 经典写法,无初始化、条件、迭代
    while (true) { ... } // 最常用
    do { ... } while (true); // 先执行后判断,至少执行1次

3. 死循环终止方式与选择

  • 常见终止方式:

    1. break语句:直接终止当前循环(本案例首选,简单直接);

    2. 条件变量控制:while (flag) { ... flag = false; ... }(适合复杂终止条件);

    3. return语句:直接返回方法,间接终止循环;

    4. 抛出异常:通过异常中断循环(不推荐,用于异常场景)。

  • 本案例选择break的原因:退出逻辑简单明确,仅在选择 “3” 时终止,无需额外变量,代码简洁高效。

面试题 5 参考答案

1. 原代码低效原因与时间复杂度

  • 低效原因:

    1. isPrime方法中循环条件j < num,需遍历从 2 到 num-1 的所有数,冗余判断(如判断 10000 是否为素数,需循环 9998 次);

    2. 未排除偶数(除 2 外,所有偶数均非素数),增加无效循环。

  • 时间复杂度:O (n²)(外层循环 n 次,内层循环平均 n/2 次)。

2. 优化后的代码与思路

  • 优化代码:

    java

    运行

    public class PrimeCountDemo {public static void main(String[] args) {int count = 0;if (2 <= 10000) count++; // 2是唯一的偶素数// 仅遍历奇数,减少一半循环for (int i = 3; i <= 10000; i += 2) {if (isPrime(i)) {count++;}}System.out.println("1-10000之间的素数个数:" + count);}
    ​private static boolean isPrime(int num) {// 优化循环条件:仅判断到根号num(因数成对出现,大于根号num的因数无需判断)for (int j = 3; j <= Math.sqrt(num); j += 2) {if (num % j == 0) {return false;}}return true;}
    }
    
  • 优化思路与数学原理:

    1. 排除偶数:除 2 外,所有偶数均能被 2 整除,无需判断;

    2. 循环条件优化:若 num 存在因数 a 和 b(a≤b),则 a≤√num、b≥√num,只需判断到√num 即可,减少循环次数;

    3. 内层循环步长为 2:仅判断奇数因数,进一步减少无效判断。

  • 优化后时间复杂度:O (n√n/4),效率提升显著。

3. 进一步优化(筛选法)核心逻辑

  • 核心原理:利用 “素数的倍数一定是非素数”,一次性标记所有非素数,无需逐个判断;

  • 实现步骤:

    1. 创建布尔数组isPrime,长度为 10001,初始值true(默认所有数为素数);

    2. isPrime[0] = isPrime[1] = false(0 和 1 非素数);

    3. 遍历 2 到√10000,若当前数为素数,则标记其所有倍数为非素数;

    4. 统计数组中true的个数,即为素数个数;

  • 筛选法时间复杂度:O (n log log n),适合大规模素数统计(如 100 万以上)。


    给老💡的一些建议:现在的水平 看这些复习博文需要 做到看道题目 秒出答案 ,简单八股举一反三。  如果看完没有问题🙋 那么恭喜你这部分基础知识扎实,如有 恭喜你发现问题!!😊

  • 多看 多练 多问  just to do it

  • 完结🎉

http://www.dtcms.com/a/540835.html

相关文章:

  • 关于网站的建设微信小程序开发平台
  • 常规八股 (w字解析,不定期更新)
  • Python界面开发2
  • 做网站还有开发文档吗做一个游戏需要什么技术
  • C语言多变量scanf循环输入深度解析:==number vs !=EOF
  • 上海殷行建设网站空间做网站
  • 吴恩达DeepLearning课程我的笔记week2
  • 建设多语种网站静态网站设计与制作书籍
  • 软件危机:开发困境与解决之道
  • NewStarCTF2025-WEEK3
  • 手机网站建设运营方案网站怎么换模板
  • 消防器具-图形识别一键计量
  • 体育彩票数据分析 python双色球数据实时分析平台+实时监控大屏 数据爬虫 可视化大屏+Flask框架 大数据 (源码)✅
  • LabelMe的安装、实例分割数据集、数据格式转换(VOC转yolo)并划分 详细教程
  • 2025年上半年架构论文《论基于事件驱动的架构设计及其应用》
  • 迁安市住房和城乡建设局网站商业计划书ppt免费模板下载
  • SQL中的JOIN该如何优化
  • 云服务器10兆可以容纳服务多少人?
  • 网站如何做内链自己建设网站怎么盈利
  • Unity Shader unity文档学习笔记(二十二):雪地几种实现方式(1. 2D贴花式 2.3D曲面细分并且实现顶点偏移)
  • 浙人医信创实践:电科金仓异构多活架构破解集团化医院转型难题
  • 多agent框架被用于分布式环境中的任务执行 是什么意思
  • 系统架构设计师备考第56天——云原生架构基础
  • CNN(卷积神经网络)和 RNN(循环神经网络)
  • 成都网站开发工资网站建设忘记密码邮箱设置
  • 延边州建设厅网站公众号网页版
  • Eclipse 重启选项详解
  • 系统分析师-信息安全-信息系统安全体系数据安全与保密
  • JavaIO笔记
  • Agentic AI 与 AI Agent的核心区别