10道Java基础高频笔试编程题

165 阅读11分钟

以下是整理后的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基础编程的核心场景,注释重点说明:

  1. 类和方法的功能定位;
  2. 边界条件处理(如null、空集合、异常输入);
  3. 核心算法逻辑(如双指针、哈希表计数、迭代优化);
  4. 关键变量和步骤的作用。

通过理解这些代码,可掌握字符串操作、数组处理、集合应用和基础算法的实现思路,应对笔试中的基础编程题。