以下是整理后的10道Java基础高频笔试编程题,每道题均添加了详细注释,涵盖核心逻辑说明、边界处理和关键步骤解析:
1. 字符串反转
/**
* 字符串反转工具类
* 功能:将输入字符串的字符顺序反转(如"abc"→"cba")
*/
public class StringReverse {
/**
* 反转字符串的核心方法
* @param str 待反转的字符串(可为null或空)
* @return 反转后的字符串;若输入为null则返回null
*/
public static String reverse(String str) {
// 边界处理:null或空字符串直接返回
if (str == null || str.isEmpty()) {
return str;
}
// 将字符串转为字符数组,便于交换操作
char[] chars = str.toCharArray();
// 双指针:左指针从头部开始,右指针从尾部开始
int left = 0;
int right = chars.length - 1;
// 循环交换左右指针指向的字符,直到指针相遇
while (left < right) {
// 交换左右字符(临时变量中转)
char temp = chars[left];
chars[left] = chars[right];
chars[right] = temp;
// 移动指针:左指针右移,右指针左移
left++;
right--;
}
// 将字符数组转回字符串并返回
return new String(chars);
}
// 测试方法
public static void main(String[] args) {
System.out.println(reverse("abc")); // 输出 "cba"
System.out.println(reverse("")); // 输出 ""(空字符串)
System.out.println(reverse(null)); // 输出 null
}
}
2. 数组中出现次数最多的元素
import java.util.HashMap;
import java.util.Map;
/**
* 数组元素统计工具类
* 功能:找出数组中出现次数最多的元素(若有多个相同次数,返回第一个出现的)
*/
public class MostFrequentElement {
/**
* 查找出现次数最多的元素
* @param arr 输入的整数数组(不能为空)
* @return 出现次数最多的元素
* @throws IllegalArgumentException 若输入数组为空则抛出异常
*/
public static int findMostFrequent(int[] arr) {
// 边界校验:数组为空时抛出异常
if (arr == null || arr.length == 0) {
throw new IllegalArgumentException("数组不能为空");
}
// 用HashMap存储元素→出现次数的映射
Map<Integer, Integer> countMap = new HashMap<>();
int maxCount = 0; // 记录最大出现次数
int result = arr[0]; // 记录结果元素(初始化为第一个元素)
// 遍历数组,统计每个元素的出现次数
for (int num : arr) {
// 计算当前元素的最新出现次数(默认0,+1)
int count = countMap.getOrDefault(num, 0) + 1;
countMap.put(num, count);
// 只有当当前次数>最大次数时才更新结果(保证第一个出现的元素优先)
if (count > maxCount) {
maxCount = count;
result = num;
}
}
return result;
}
// 测试方法
public static void main(String[] args) {
int[] arr = {1, 2, 3, 2, 2, 3, 1}; // 元素2出现3次(最多)
System.out.println(findMostFrequent(arr)); // 输出 2
}
}
3. 两个数组的交集
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 数组交集计算工具类
* 功能:计算两个数组的交集(元素出现次数与两个数组中较少的一致)
*/
public class ArrayIntersection {
/**
* 计算两个数组的交集
* @param nums1 第一个整数数组
* @param nums2 第二个整数数组
* @return 交集数组(元素顺序与nums2中出现顺序一致)
*/
public static int[] intersect(int[] nums1, int[] nums2) {
// 用HashMap统计第一个数组中元素的出现次数
Map<Integer, Integer> countMap = new HashMap<>();
for (int num : nums1) {
// 若元素已存在则次数+1,否则初始化为1
countMap.put(num, countMap.getOrDefault(num, 0) + 1);
}
// 用List暂存交集元素(动态扩容,避免数组长度固定的问题)
List<Integer> resultList = new ArrayList<>();
// 遍历第二个数组,匹配交集元素
for (int num : nums2) {
// 若元素在第一个数组中存在且剩余次数>0
if (countMap.containsKey(num) && countMap.get(num) > 0) {
resultList.add(num); // 加入结果集
countMap.put(num, countMap.get(num) - 1); // 次数-1(避免重复计算)
}
}
// 将List转换为int数组(笔试中常见的集合转数组操作)
int[] result = new int[resultList.size()];
for (int i = 0; i < resultList.size(); i++) {
result[i] = resultList.get(i);
}
return result;
}
// 测试方法
public static void main(String[] args) {
int[] nums1 = {4, 9, 5};
int[] nums2 = {9, 4, 9, 8, 4}; // 交集元素为4(2次)、9(1次)
int[] res = intersect(nums1, nums2);
// 输出结果:4 9(或9 4,取决于nums2中出现顺序)
for (int num : res) {
System.out.print(num + " ");
}
}
}
4. 斐波那契数列(递归+迭代)
/**
* 斐波那契数列工具类
* 功能:计算斐波那契数列第n项(f(0)=0, f(1)=1, f(n)=f(n-1)+f(n-2))
*/
public class Fibonacci {
/**
* 迭代法计算斐波那契数列(推荐,时间复杂度O(n),空间复杂度O(1))
* @param n 数列的项数(n≥0)
* @return 第n项的值
* @throws IllegalArgumentException 若n为负数则抛出异常
*/
public static int fibIterative(int n) {
// 边界校验:n为负数时不合法
if (n < 0) {
throw new IllegalArgumentException("n不能为负数");
}
// base case:n=0返回0,n=1返回1
if (n == 0) return 0;
if (n == 1) return 1;
// 迭代变量:a表示f(n-2),b表示f(n-1)
int a = 0, b = 1;
// 从第2项开始计算,直到第n项
for (int i = 2; i <= n; i++) {
int c = a + b; // 当前项 = 前两项之和
a = b; // 更新f(n-2)为上一轮的f(n-1)
b = c; // 更新f(n-1)为当前项
}
return b; // 循环结束后,b即为f(n)
}
/**
* 递归法计算斐波那契数列(时间复杂度O(2^n),不推荐用于n≥30的场景)
* @param n 数列的项数(n≥0)
* @return 第n项的值
* @throws IllegalArgumentException 若n为负数则抛出异常
*/
public static int fibRecursive(int n) {
if (n < 0) {
throw new IllegalArgumentException("n不能为负数");
}
// 递归终止条件
if (n == 0) return 0;
if (n == 1) return 1;
// 递归公式:f(n) = f(n-1) + f(n-2)
return fibRecursive(n - 1) + fibRecursive(n - 2);
}
// 测试方法
public static void main(String[] args) {
// 斐波那契数列:0,1,1,2,3,5(第5项为5)
System.out.println(fibIterative(5)); // 输出 5
System.out.println(fibRecursive(5)); // 输出 5
}
}
5. 验证回文串
/**
* 回文串验证工具类
* 功能:判断字符串是否为回文串(只考虑字母和数字,忽略大小写)
*/
public class PalindromeChecker {
/**
* 验证字符串是否为回文串
* @param s 待验证的字符串(可为null)
* @return 若为回文串则返回true,否则返回false
*/
public static boolean isPalindrome(String s) {
// 边界处理:null直接返回false
if (s == null) return false;
// 统一转为小写,忽略大小写差异(如'A'和'a'视为相同)
s = s.toLowerCase();
// 双指针:左指针从头部,右指针从尾部
int left = 0;
int right = s.length() - 1;
// 指针向中间移动,直到相遇
while (left < right) {
// 跳过左侧非字母数字的字符(如空格、标点)
while (left < right && !Character.isLetterOrDigit(s.charAt(left))) {
left++;
}
// 跳过右侧非字母数字的字符
while (left < right && !Character.isLetterOrDigit(s.charAt(right))) {
right--;
}
// 比较当前左右指针的字符是否相同
if (s.charAt(left) != s.charAt(right)) {
return false; // 不同则不是回文串
}
// 移动指针继续比较
left++;
right--;
}
// 所有字符匹配,是回文串
return true;
}
// 测试方法
public static void main(String[] args) {
// "A man, a plan, a canal: Panama" → 忽略符号和空格后是回文
System.out.println(isPalindrome("A man, a plan, a canal: Panama")); // true
System.out.println(isPalindrome("race a car")); // false("raceacar"不是回文)
}
}
6. 冒泡排序
/**
* 冒泡排序工具类
* 功能:对整数数组进行升序排序(相邻元素比较交换)
*/
public class BubbleSort {
/**
* 冒泡排序核心方法
* @param arr 待排序的整数数组(可为null或空数组)
*/
public static void bubbleSort(int[] arr) {
// 边界处理:null或长度≤1的数组无需排序
if (arr == null || arr.length <= 1) {
return;
}
int n = arr.length;
boolean swapped; // 标记本轮是否发生交换,用于优化
// 外层循环:控制排序轮数(最多n-1轮)
for (int i = 0; i < n - 1; i++) {
swapped = false; // 初始化本轮未交换
// 内层循环:每轮比较相邻元素,将大的元素"冒泡"到尾部
// 优化:每轮结束后,尾部i个元素已排序,无需再比较
for (int j = 0; j < n - 1 - i; j++) {
// 若当前元素>下一个元素,交换位置
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true; // 标记发生交换
}
}
// 若本轮未发生交换,说明数组已有序,提前退出
if (!swapped) {
break;
}
}
}
// 测试方法
public static void main(String[] args) {
int[] arr = {64, 34, 25, 12, 22, 11, 90};
bubbleSort(arr);
// 输出排序结果:11 12 22 25 34 64 90
for (int num : arr) {
System.out.print(num + " ");
}
}
}
7. 统计字符串中每个字符出现次数
import java.util.HashMap;
import java.util.Map;
/**
* 字符计数工具类
* 功能:统计字符串中每个字符(包括空格、符号)的出现次数
*/
public class CharacterCounter {
/**
* 统计字符串中字符的出现次数并输出
* @param str 待统计的字符串(可为null)
*/
public static void countCharacters(String str) {
// 边界处理:null时提示信息
if (str == null) {
System.out.println("输入字符串为null");
return;
}
// 用HashMap存储字符→出现次数的映射
Map<Character, Integer> countMap = new HashMap<>();
// 遍历字符串的每个字符
for (char c : str.toCharArray()) {
// 累加计数:若字符已存在则+1,否则初始化为1
countMap.put(c, countMap.getOrDefault(c, 0) + 1);
}
// 遍历Map,输出每个字符的出现次数
for (Map.Entry<Character, Integer> entry : countMap.entrySet()) {
System.out.println("字符 '" + entry.getKey() + "' 出现次数:" + entry.getValue());
}
}
// 测试方法
public static void main(String[] args) {
countCharacters("Hello, World!");
// 输出示例:
// 字符 ' ' 出现次数:1
// 字符 '!' 出现次数:1
// 字符 ',' 出现次数:1
// 字符 'H' 出现次数:1
// 字符 'e' 出现次数:1
// 字符 'l' 出现次数:3
// 字符 'o' 出现次数:2
// 字符 'W' 出现次数:1
// 字符 'r' 出现次数:1
// 字符 'd' 出现次数:1
}
}
8. 求两个数的最大公约数(GCD)
/**
* 最大公约数计算工具类
* 功能:用欧几里得算法(辗转相除法)求两个正整数的最大公约数
*/
public class GCDCalculator {
/**
* 计算两个正整数的最大公约数(GCD)
* @param a 第一个正整数
* @param b 第二个正整数
* @return 最大公约数(大于0的整数)
* @throws IllegalArgumentException 若输入为非正整数则抛出异常
*/
public static int gcd(int a, int b) {
// 边界校验:输入必须为正整数
if (a <= 0 || b <= 0) {
throw new IllegalArgumentException("输入必须为正整数");
}
// 欧几里得算法(辗转相除法)核心逻辑:
// gcd(a, b) = gcd(b, a % b),直到b=0时,a即为结果
while (b != 0) {
int temp = b; // 暂存b的值
b = a % b; // 用a除以b的余数更新b
a = temp; // 用原来的b更新a
}
return a; // 当b=0时,a即为最大公约数
}
// 测试方法
public static void main(String[] args) {
System.out.println(gcd(12, 18)); // 12和18的GCD是6
System.out.println(gcd(7, 5)); // 7和5的GCD是1(互质)
}
}
9. 合并两个有序数组
/**
* 有序数组合并工具类
* 功能:将两个升序排序的数组合并为一个新的升序数组
*/
public class MergeSortedArrays {
/**
* 合并两个有序数组
* @param arr1 第一个升序数组(可为null)
* @param arr2 第二个升序数组(可为null)
* @return 合并后的升序数组
*/
public static int[] merge(int[] arr1, int[] arr2) {
// 边界处理:若其中一个数组为null,直接返回另一个
if (arr1 == null) return arr2;
if (arr2 == null) return arr1;
// 结果数组长度 = 两个数组长度之和
int[] result = new int[arr1.length + arr2.length];
// 三指针:i遍历arr1,j遍历arr2,k指向result的当前位置
int i = 0, j = 0, k = 0;
// 双指针同步遍历两个数组,比较元素大小并放入结果数组
while (i < arr1.length && j < arr2.length) {
// 取较小的元素放入结果数组,并移动对应指针
if (arr1[i] <= arr2[j]) {
result[k++] = arr1[i++];
} else {
result[k++] = arr2[j++];
}
}
// 处理arr1中剩余的元素(若有)
while (i < arr1.length) {
result[k++] = arr1[i++];
}
// 处理arr2中剩余的元素(若有)
while (j < arr2.length) {
result[k++] = arr2[j++];
}
return result;
}
// 测试方法
public static void main(String[] args) {
int[] arr1 = {1, 3, 5};
int[] arr2 = {2, 4, 6};
int[] merged = merge(arr1, arr2);
// 输出合并结果:1 2 3 4 5 6
for (int num : merged) {
System.out.print(num + " ");
}
}
}
10. 打印1到n之间的所有质数
/**
* 质数打印工具类
* 功能:打印1到n之间的所有质数(质数:大于1的自然数,仅能被1和自身整除)
*/
public class PrimePrinter {
/**
* 打印1到n之间的所有质数
* @param n 范围上限(正整数)
*/
public static void printPrimes(int n) {
// 边界处理:n<2时无质数(质数定义为大于1的自然数)
if (n < 2) {
System.out.println("无质数(质数大于1)");
return;
}
System.out.println("1到" + n + "之间的质数:");
// 遍历2到n的所有数,判断是否为质数
for (int i = 2; i <= n; i++) {
if (isPrime(i)) {
System.out.print(i + " ");
}
}
}
/**
* 判断一个数是否为质数(辅助方法)
* @param num 待判断的整数
* @return 若为质数则返回true,否则返回false
*/
private static boolean isPrime(int num) {
// 小于等于1的数不是质数
if (num <= 1) return false;
// 2是唯一的偶数质数
if (num == 2) return true;
// 偶数(除2外)一定不是质数
if (num % 2 == 0) return false;
// 只需检查3到√num之间的奇数(优化:减少循环次数)
// 原因:若num有因数,必有一个≤√num
for (int i = 3; i <= Math.sqrt(num); i += 2) {
if (num % i == 0) { // 存在除1和自身外的因数
return false;
}
}
// 未找到其他因数,是质数
return true;
}
// 测试方法
public static void main(String[] args) {
printPrimes(30); // 输出 2 3 5 7 11 13 17 19 23 29
}
}
总结
以上代码覆盖了Java基础编程的核心场景,注释重点说明:
- 类和方法的功能定位;
- 边界条件处理(如null、空集合、异常输入);
- 核心算法逻辑(如双指针、哈希表计数、迭代优化);
- 关键变量和步骤的作用。
通过理解这些代码,可掌握字符串操作、数组处理、集合应用和基础算法的实现思路,应对笔试中的基础编程题。