30个最常见算法题及其Java实现和详细解析

 更新时间:2026年01月19日 10:44:07   作者:M.Z.Q  
在技术笔试中,算法题主要考察对基础数据结构(数组、链表、树、栈 / 队列、图)的掌握,以及经典算法思想(动态规划、贪心、查找排序、回溯)的应用,这篇文章主要介绍了30个最常见算法题及其Java实现和详细解析的相关资料,需要的朋友可以参考下

前言

算法是计算机科学的核心,掌握常见算法问题对Java开发者至关重要。本文精选30个高频算法题,附Java实现和详细解析,助你提升编程和面试能力。

1. 两数之和 (Two Sum)

问题描述​:给定一个整数数组 nums和一个目标值 target,请在数组中找出和为目标值的两个整数,并返回它们的数组下标。

Java解答​:

public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement)) {
            return new int[]{map.get(complement), i};
        }
        map.put(nums[i], i);
    }
    throw new IllegalArgumentException("No two sum solution");
}

解析​:使用哈希表​(HashMap)存储元素值及其索引。对于每个元素,计算其与目标值的差值,检查差值是否已在哈希表中。若存在,直接返回结果;否则将当前元素存入哈希表。​时间复杂度为O(n)​,空间复杂度为O(n)。

2. 反转链表 (Reverse Linked List)

问题描述​:反转一个单链表。

Java解答​:

public ListNode reverseList(ListNode head) {
    ListNode prev = null;
    ListNode curr = head;
    while (curr != null) {
        ListNode nextTemp = curr.next;
        curr.next = prev;
        prev = curr;
        curr = nextTemp;
    }
    return prev;
}

解析​:采用迭代法,使用三个指针prevcurrnextTemp。遍历链表时,将当前节点的next指针指向前一个节点,然后移动指针继续处理,直到链表末尾。​时间复杂度O(n)​,空间复杂度O(1)。

3. 字符串判断回文 (Valid Palindrome)

问题描述​:判断一个字符串是否是回文串​(只考虑字母和数字字符,忽略大小写)。

Java解答​:

public boolean isPalindrome(String s) {
    int left = 0, 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 (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) {
            return false;
        }
        left++;
        right--;
    }
    return true;
}

解析​:使用双指针技术,一个从字符串开头向右移动,一个从末尾向左移动。跳过非字母数字字符,比较字符是否相等(忽略大小写)。​时间复杂度O(n)​,空间复杂度O(1)。

4. 合并两个有序链表 (Merge Two Sorted Lists)

问题描述​:将两个升序链表合并为一个新的升序链表。

Java解答​:

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    ListNode dummy = new ListNode(-1);
    ListNode current = dummy;
    
    while (l1 != null && l2 != null) {
        if (l1.val <= l2.val) {
            current.next = l1;
            l1 = l1.next;
        } else {
            current.next = l2;
            l2 = l2.next;
        }
        current = current.next;
    }
    
    current.next = (l1 != null) ? l1 : l2;
    return dummy.next;
}

解析​:创建虚拟头节点dummy简化操作。比较两链表当前节点值,将较小节点连接到新链表,直到某一链表遍历完,最后将剩余部分直接链接。​时间复杂度O(n+m)​,空间复杂度O(1)。

5. 二分查找 (Binary Search)

问题描述​:在排序数组中查找特定元素,返回其索引,未找到返回-1。

Java解答​:

public int binarySearch(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;
}

解析​:​二分查找通过维护左右边界,每次比较中间元素与目标值,缩小一半搜索范围。​注意边界条件​(left <= right)。​时间复杂度O(log n)​,空间复杂度O(1)。

6. 最大子序和 (Maximum Subarray)

问题描述​:找出整数数组中连续子数组的最大和。

Java解答​:

public int maxSubArray(int[] nums) {
    int maxSoFar = nums[0];
    int maxEndingHere = nums[0];
    
    for (int i = 1; i < nums.length; i++) {
        maxEndingHere = Math.max(nums[i], maxEndingHere + nums[i]);
        maxSoFar = Math.max(maxSoFar, maxEndingHere);
    }
    
    return maxSoFar;
}

解析​:使用Kadane算法。遍历数组,对于每个元素,决定是将其加入当前子数组还是开始新的子数组。maxEndingHere记录当前子数组和,maxSoFar记录全局最大和。​时间复杂度O(n)​,空间复杂度O(1)。

7. 爬楼梯问题 (Climbing Stairs)

问题描述​:每次可以爬1或2阶台阶,有多少种不同方法爬到n阶楼顶?

Java解答​:

public int climbStairs(int n) {
    if (n == 1) return 1;
    int first = 1;
    int second = 2;
    for (int i = 3; i <= n; i++) {
        int third = first + second;
        first = second;
        second = third;
    }
    return second;
}

解析​:这是动态规划问题,本质是求斐波那契数列。定义状态dp[i]为到达第i阶的方法数,状态转移方程:dp[i] = dp[i-1] + dp[i-2]。使用滚动数组优化空间。​时间复杂度O(n)​,空间复杂度O(1)。

8. 二叉树的层序遍历 (Binary Tree Level Order Traversal)

问题描述​:返回二叉树按层序遍历的节点值。

Java解答​:

public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> result = new ArrayList<>();
    if (root == null) return result;
    
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    
    while (!queue.isEmpty()) {
        int levelSize = queue.size();
        List<Integer> currentLevel = new ArrayList<>();
        for (int i = 0; i < levelSize; i++) {
            TreeNode node = queue.poll();
            currentLevel.add(node.val);
            if (node.left != null) queue.offer(node.left);
            if (node.right != null) queue.offer(node.right);
        }
        result.add(currentLevel);
    }
    
    return result;
}

解析​:使用队列实现广度优先搜索(BFS)​。每次处理一层节点,将其子节点加入队列。​时间复杂度O(n)​,空间复杂度O(n)。

9. 有效的括号 (Valid Parentheses)

问题描述​:判断字符串中的括号是否有效闭合

Java解答​:

public boolean isValid(String s) {
    Stack<Character> stack = new Stack<>();
    for (char c : s.toCharArray()) {
        if (c == '(' || c == '[' || c == '{') {
            stack.push(c);
        } else {
            if (stack.isEmpty()) return false;
            char top = stack.pop();
            if ((c == ')' && top != '(') || 
                (c == ']' && top != '[') || 
                (c == '}' && top != '{')) {
                return false;
            }
        }
    }
    return stack.isEmpty();
}

解析​:使用数据结构。遇到左括号入栈,遇到右括号检查栈顶是否匹配。​时间复杂度O(n)​,空间复杂度O(n)。

10. 寻找数组中的重复数 (Find the Duplicate Number)

问题描述​:给定包含1到n整数的数组,假设只有一个重复数,找出它。

Java解答​:

public int findDuplicate(int[] nums) {
    int slow = nums[0];
    int fast = nums[0];
    
    do {
        slow = nums[slow];
        fast = nums[nums[fast]];
    } while (slow != fast);
    
    slow = nums[0];
    while (slow != fast) {
        slow = nums[slow];
        fast = nums[fast];
    }
    
    return slow;
}

解析​:将数组视为链表,使用Floyd判圈算法​(快慢指针)。快指针每次两步,慢指针每次一步,相遇后重置慢指针,两指针同速前进,再次相遇点为重复数。​时间复杂度O(n)​,空间复杂度O(1)。

11. 二叉树的最大深度 (Maximum Depth of Binary Tree)

问题描述​:给定二叉树,找出其最大深度

Java解答​:

public int maxDepth(TreeNode root) {
    if (root == null) return 0;
    int leftDepth = maxDepth(root.left);
    int rightDepth = maxDepth(root.right);
    return Math.max(leftDepth, rightDepth) + 1;
}

解析​:使用递归深度优先搜索(DFS)。二叉树的最大深度等于左右子树最大深度加1。​时间复杂度O(n)​,空间复杂度O(h)(h为树高)。

12. 最长递增子序列 (Longest Increasing Subsequence)

问题描述​:找出数组中最长严格递增子序列的长度。

Java解答​:

public int lengthOfLIS(int[] nums) {
    if (nums.length == 0) return 0;
    int[] dp = new int[nums.length];
    Arrays.fill(dp, 1);
    int maxAns = 1;
    
    for (int i = 1; i < nums.length; i++) {
        for (int j = 0; j < i; j++) {
            if (nums[i] > nums[j]) {
                dp[i] = Math.max(dp[i], dp[j] + 1);
            }
        }
        maxAns = Math.max(maxAns, dp[i]);
    }
    
    return maxAns;
}

解析​:使用动态规划。定义dp[i]为以第i个元素结尾的最长递增子序列长度。对于每个元素,检查之前所有元素,若当前元素更大,则更新dp[i]。​时间复杂度O(n²)​,空间复杂度O(n)。

13. 二叉树的前序遍历 (Binary Tree Preorder Traversal)

问题描述​:返回二叉树前序遍历的节点值。

Java解答​:

public List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    Stack<TreeNode> stack = new Stack<>();
    if (root != null) stack.push(root);
    
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        result.add(node.val);
        if (node.right != null) stack.push(node.right);
        if (node.left != null) stack.push(node.left);
    }
    
    return result;
}

解析​:使用模拟递归过程。前序遍历顺序为"根-左-右",所以先将右子节点入栈,再将左子节点入栈。​时间复杂度O(n)​,空间复杂度O(n)。

14. 字符串转换整数 (atoi) (String to Integer (atoi))

问题描述​:实现字符串到整数的转换。

Java解答​:

public int myAtoi(String s) {
    if (s == null || s.length() == 0) return 0;
    
    int index = 0, sign = 1, total = 0;
    // 跳过空格
    while (index < s.length() && s.charAt(index) == ' ') index++;
    
    if (index == s.length()) return 0;
    
    // 处理符号
    if (s.charAt(index) == '+' || s.charAt(index) == '-') {
        sign = s.charAt(index) == '+' ? 1 : -1;
        index++;
    }
    
    while (index < s.length()) {
        int digit = s.charAt(index) - '0';
        if (digit < 0 || digit > 9) break;
        
        // 检查溢出
        if (Integer.MAX_VALUE / 10 < total || 
            (Integer.MAX_VALUE / 10 == total && Integer.MAX_VALUE % 10 < digit)) {
            return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
        }
        
        total = total * 10 + digit;
        index++;
    }
    
    return total * sign;
}

解析​:处理空格、正负号和数字字符。​关键处理整数溢出,检查当前结果是否超过32位整数范围。​时间复杂度O(n)​,空间复杂度O(1)。

15. 删除链表的倒数第N个节点 (Remove Nth Node From End of List)

问题描述​:删除链表的倒数第n个节点

Java解答​:

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode dummy = new ListNode(0);
    dummy.next = head;
    ListNode first = dummy;
    ListNode second = dummy;
    
    for (int i = 0; i <= n; i++) {
        first = first.next;
    }
    
    while (first != null) {
        first = first.next;
        second = second.next;
    }
    
    second.next = second.next.next;
    return dummy.next;
}

解析​:使用双指针技术。第一个指针先移动n+1步,然后两个指针同时移动,当第一个指针到达末尾时,第二个指针指向待删除节点的前一个节点。​时间复杂度O(n)​,空间复杂度O(1)。

16. 括号生成 (Generate Parentheses)

问题描述​:数字n代表生成括号的对数,生成所有有效的括号组合

Java解答​:

public List<String> generateParenthesis(int n) {
    List<String> result = new ArrayList<>();
    backtrack(result, "", 0, 0, n);
    return result;
}

private void backtrack(List<String> result, String current, int open, int close, int max) {
    if (current.length() == max * 2) {
        result.add(current);
        return;
    }
    
    if (open < max) {
        backtrack(result, current + "(", open + 1, close, max);
    }
    if (close < open) {
        backtrack(result, current + ")", open, close + 1, max);
    }
}

解析​:使用回溯算法。跟踪当前开括号和闭括号数量,只有开括号数小于n时可添加开括号,只有闭括号数小于开括号数时可添加闭括号。​时间复杂度O(4^n/√n)​,空间复杂度O(n)。

17. 实现strStr() (Implement strStr())

问题描述​:返回字符串中第一个匹配项的下标,不存在返回-1。

Java解答​:

public int strStr(String haystack, String needle) {
    if (needle.isEmpty()) return 0;
    
    for (int i = 0; i <= haystack.length() - needle.length(); i++) {
        for (int j = 0; j < needle.length() && haystack.charAt(i + j) == needle.charAt(j); j++) {
            if (j == needle.length() - 1) return i;
        }
    }
    
    return -1;
}

解析​:​暴力匹配,遍历原字符串,对于每个位置,检查是否与模式串匹配。也可使用KMP等高效算法。​平均时间复杂度O(n+m)​,最坏O(n×m)。

18. 搜索旋转排序数组 (Search in Rotated Sorted Array)

问题描述​:​旋转过的升序数组中搜索目标值,返回索引。

Java解答​:

public int search(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) return mid;
        
        if (nums[left] <= nums[mid]) { // 左半部分有序
            if (nums[left] <= target && target < nums[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        } else { // 右半部分有序
            if (nums[mid] < target && target <= nums[right]) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
    }
    
    return -1;
}

解析​:​修改的二分查找。每次确定哪一半是有序的,并检查目标是否在有序部分内。​时间复杂度O(log n)​,空间复杂度O(1)。

19. 在排序数组中查找元素的第一个和最后一个位置 (Find First and Last Position of Element in Sorted Array)

问题描述​:给定排序数组和目标值,找出目标值开始和结束位置

Java解答​:

public int[] searchRange(int[] nums, int target) {
    int[] result = {-1, -1};
    result[0] = findBound(nums, target, true);
    if (result[0] != -1) {
        result[1] = findBound(nums, target, false);
    }
    return result;
}

private int findBound(int[] nums, int target, boolean isFirst) {
    int left = 0, right = nums.length - 1;
    int index = -1;
    
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            index = mid;
            if (isFirst) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    
    return index;
}

解析​:使用两次二分查找,第一次找起始位置,第二次找结束位置。找到目标后继续向相应方向搜索。​时间复杂度O(log n)​,空间复杂度O(1)。

20. 组合总和 (Combination Sum)

问题描述​:找出数组中所有可以使数字和为target的唯一组合

Java解答​:

public List<List<Integer>> combinationSum(int[] candidates, int target) {
    List<List<Integer>> result = new ArrayList<>();
    Arrays.sort(candidates);
    backtrack(result, new ArrayList<>(), candidates, target, 0);
    return result;
}

private void backtrack(List<List<Integer>> result, List<Integer> temp, 
                      int[] candidates, int remain, int start) {
    if (remain < 0) return;
    if (remain == 0) {
        result.add(new ArrayList<>(temp));
        return;
    }
    
    for (int i = start; i < candidates.length; i++) {
        temp.add(candidates[i]);
        backtrack(result, temp, candidates, remain - candidates[i], i);
        temp.remove(temp.size() - 1);
    }
}

解析​:使用回溯算法。对数组排序后,递归尝试每个候选数,减少目标值,允许重复使用同一元素。​时间复杂度O(N^target)​,空间复杂度O(target)。

21. 全排列 (Permutations)

问题描述​:给定没有重复数字的序列,返回其所有可能排列。

Java解答​:

public List<List<Integer>> permute(int[] nums) {
    List<List<Integer>> result = new ArrayList<>();
    backtrack(result, new ArrayList<>(), nums, new boolean[nums.length]);
    return result;
}

private void backtrack(List<List<Integer>> result, List<Integer> temp, 
                      int[] nums, boolean[] used) {
    if (temp.size() == nums.length) {
        result.add(new ArrayList<>(temp));
        return;
    }
    
    for (int i = 0; i < nums.length; i++) {
        if (used[i]) continue;
        used[i] = true;
        temp.add(nums[i]);
        backtrack(result, temp, nums, used);
        temp.remove(temp.size() - 1);
        used[i] = false;
    }
}

解析​:使用回溯算法used数组标记已使用元素。当临时列表大小等于原数组时,找到一个排列。​时间复杂度O(n!)​,空间复杂度O(n)。

22. 合并两个有序数组 (Merge Sorted Array)

问题描述​:将两个有序数组合并到第一个数组中。

Java解答​:

public void merge(int[] nums1, int m, int[] nums2, int n) {
    int p1 = m - 1, p2 = n - 1, p = m + n - 1;
    
    while (p1 >= 0 && p2 >= 0) {
        if (nums1[p1] > nums2[p2]) {
            nums1[p--] = nums1[p1--];
        } else {
            nums1[p--] = nums2[p2--];
        }
    }
    
    System.arraycopy(nums2, 0, nums1, 0, p2 + 1);
}

解析​:使用三指针,从后向前处理。比较两数组元素,较大者放入nums1末尾。​时间复杂度O(m+n)​,空间复杂度O(1)。

23. 验证二叉搜索树 (Validate Binary Search Tree)

问题描述​:判断二叉树是否是有效的二叉搜索树

Java解答​:

public boolean isValidBST(TreeNode root) {
    return validate(root, null, null);
}
 
private boolean validate(TreeNode node, Integer low, Integer high) {
    if (node == null) return true;
    
    if ((low != null && node.val <= low) || (high != null && node.val >= high)) {
        return false;
    }
    
    return validate(node.left, low, node.val) && validate(node.right, node.val, high);
}

解析​:使用递归,传递上下界。左子树所有节点值应小于当前节点值,右子树所有节点值应大于当前节点值。​时间复杂度O(n)​,空间复杂度O(n)。

24. 对称二叉树 (Symmetric Tree)

问题描述​:检查二叉树是否是镜像对称的。

Java解答​:

public boolean isSymmetric(TreeNode root) {
    return isMirror(root, root);
}
 
private boolean isMirror(TreeNode t1, TreeNode t2) {
    if (t1 == null && t2 == null) return true;
    if (t1 == null || t2 == null) return false;
    return (t1.val == t2.val) && 
           isMirror(t1.left, t2.right) && 
           isMirror(t1.right, t2.left);
}

解析​:使用递归比较左右子树。两树对称当且仅当根节点值相等,且左子树与右子树镜像对称。​时间复杂度O(n)​,空间复杂度O(n)。

25. 二叉树的中序遍历 (Binary Tree Inorder Traversal)

问题描述​:返回二叉树中序遍历的节点值。

Java解答​:

public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    Stack<TreeNode> stack = new Stack<>();
    TreeNode curr = root;
    
    while (curr != null || !stack.isEmpty()) {
        while (curr != null) {
            stack.push(curr);
            curr = curr.left;
        }
        curr = stack.pop();
        result.add(curr.val);
        curr = curr.right;
    }
    
    return result;
}

解析​:使用模拟递归过程。中序遍历顺序为"左-根-右",先遍历左子树到底,处理节点,再处理右子树。​时间复杂度O(n)​,空间复杂度O(n)。

26. 最长公共前缀 (Longest Common Prefix)

问题描述​:查找字符串数组中的最长公共前缀

Java解答​:

public String longestCommonPrefix(String[] strs) {
    if (strs == null || strs.length == 0) return "";
    
    String prefix = strs[0];
    for (int i = 1; i < strs.length; i++) {
        while (strs[i].indexOf(prefix) != 0) {
            prefix = prefix.substring(0, prefix.length() - 1);
            if (prefix.isEmpty()) return "";
        }
    }
    
    return prefix;
}

解析​:以第一个字符串作为初始前缀,依次与后续字符串比较,不断缩短前缀直到匹配。​时间复杂度O(S)​​(S为所有字符数),空间复杂度O(1)。

27. K个一组翻转链表 (Reverse Nodes in k-Group)

问题描述​:每k个节点一组进行翻转,返回修改后的链表。

Java解答​:

public ListNode reverseKGroup(ListNode head, int k) {
    ListNode dummy = new ListNode(0);
    dummy.next = head;
    ListNode prev = dummy;
    
    while (head != null) {
        ListNode start = head;
        ListNode end = prev;
        
        for (int i = 0; i < k; i++) {
            end = end.next;
            if (end == null) return dummy.next;
        }
        
        ListNode next = end.next;
        end.next = null;
        prev.next = reverse(start);
        start.next = next;
        
        prev = start;
        head = next;
    }
    
    return dummy.next;
}
 
private ListNode reverse(ListNode head) {
    ListNode prev = null;
    ListNode curr = head;
    while (curr != null) {
        ListNode next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
    }
    return prev;
}

解析​:使用虚拟头节点简化操作。找到每k个节点的起始和结束位置,翻转该段子链表,再与前后部分连接。​时间复杂度O(n)​,空间复杂度O(1)。

28. 删除排序数组中的重复项 (Remove Duplicates from Sorted Array)

问题描述​:​原地删除排序数组中的重复项,返回新长度。

Java解答​:

public int removeDuplicates(int[] nums) {
    if (nums.length == 0) return 0;
    int i = 0;
    for (int j = 1; j < nums.length; j++) {
        if (nums[j] != nums[i]) {
            i++;
            nums[i] = nums[j];
        }
    }
    return i + 1;
}

解析​:使用双指针技术。慢指针i跟踪唯一元素位置,快指针j遍历数组。当发现不同元素时,移动慢指针并更新值。​时间复杂度O(n)​,空间复杂度O(1)。

29. 盛最多水的容器 (Container With Most Water)

问题描述​:找出两条线,使得它们与x轴共同构成的容器可以容纳最多的水。

Java解答​:

public int maxArea(int[] height) {
    int left = 0, right = height.length - 1;
    int maxArea = 0;
    
    while (left < right) {
        int area = Math.min(height[left], height[right]) * (right - left);
        maxArea = Math.max(maxArea, area);
        
        if (height[left] < height[right]) {
            left++;
        } else {
            right--;
        }
    }
    
    return maxArea;
}

解析​:使用双指针从两端向中间移动。容量由较矮的线和宽度决定。每次移动较矮一侧的指针,因为移动较高侧的指针不会增加容量。​时间复杂度O(n)​,空间复杂度O(1)。

30. 寻找两个正序数组的中位数 (Median of Two Sorted Arrays)

问题描述​:找出两个正序数组的中位数,要求时间复杂度为O(log (m+n))。

Java解答​:

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    if (nums1.length > nums2.length) {
        return findMedianSortedArrays(nums2, nums1);
    }
    
    int x = nums1.length, y = nums2.length;
    int low = 0, high = x;
    
    while (low <= high) {
        int partitionX = (low + high) / 2;
        int partitionY = (x + y + 1) / 2 - partitionX;
        
        int maxX = (partitionX == 0) ? Integer.MIN_VALUE : nums1[partitionX - 1];
        int minX = (partitionX == x) ? Integer.MAX_VALUE : nums1[partitionX];
        
        int maxY = (partitionY == 0) ? Integer.MIN_VALUE : nums2[partitionY - 1];
        int minY = (partitionY == y) ? Integer.MAX_VALUE : nums2[partitionY];
        
        if (maxX <= minY && maxY <= minX) {
            if ((x + y) % 2 == 0) {
                return (Math.max(maxX, maxY) + Math.min(minX, minY)) / 2.0;
            } else {
                return Math.max(maxX, maxY);
            }
        } else if (maxX > minY) {
            high = partitionX - 1;
        } else {
            low = partitionX + 1;
        }
    }
    
    throw new IllegalArgumentException();
}

解析​:使用二分查找。对较短数组进行分割,确保左半部分全部小于右半部分。找到正确分割后,根据总数奇偶性计算中位数。​时间复杂度O(log(min(m,n)))​,空间复杂度O(1)。

总结

不同数据规模下的复杂度选择建议

根据问题规模,可以参考以下选择标准:

数据规模 (n)

可接受的复杂度

推荐算法示例

n ≤ 100

O(n³), O(n²)

冒泡排序、简单动态规划

n ≤ 1,000

O(n²), O(n log n)

快速排序、简单图算法

n ≤ 100,000

O(n log n)

归并排序、堆排序

n ≤ 1,000,000

O(n), O(n log n)

计数排序、并查集

n > 1,000,000

O(log n), O(1)

二分查找、哈希查找

实际应用中的操作次数对比(假设n=1000)

复杂度

操作次数(近似)

实际应用场景

效率评价

O(1)

1

哈希表访问、数组索引

最优,与输入规模无关

O(log n)

~10

二分查找、平衡树操作

极高效,增速最慢

O(n)

1000

遍历数组/链表

高效,线性增长

O(n log n)

~10,000

快速排序、归并排序

较高效,适用于大数据

O(n²)

1,000,000

冒泡排序、简单矩阵乘法

低效,小规模数据可用

O(n³)

1,000,000,000

三重循环(如暴力算法)

非常低效,避免大规模

O(2ⁿ)

~10³⁰¹

子集生成、穷举组合

不可行,指数爆炸

O(n!)

~10²⁵⁶⁸

全排列生成、旅行商问题(暴力)

完全不可行

时间与空间复杂度的权衡

在实际算法设计中,经常需要在时间复杂度和空间复杂度之间进行权衡:

  1. 以空间换时间​:使用额外的存储空间来降低时间复杂度

    • 示例​:哈希表加速查找(从O(n)到O(1))

    • 示例​:动态规划中的记忆化存储

  2. 以时间换空间​:减少空间使用,但可能增加时间复杂度

    • 示例​:原地排序算法(如堆排序)

    • 示例​:流式处理大数据集

  3. 固定空间算法​:无论输入规模如何,使用恒定空间

    • 示例​:迭代算法代替递归算法减少栈空间使用

如何分析算法复杂度

  1. 时间复杂度分析​:

    • 找出基本操作(最频繁执行的操作)

    • 计算基本操作执行次数与输入规模n的关系

    • 使用大O表示法表示最高阶项,忽略常数因子和低阶项

  2. 空间复杂度分析​:

    • 统计算法运行过程中动态分配的额外存储空间

    • 包括变量、数据结构、递归调用栈等

    • 同样使用大O表示法表示

  3. 考虑最坏情况​:复杂度分析通常关注最坏情况下的性能,这提供了算法性能的保证上限。

掌握这些经典算法题不仅能帮助你在技术面试中脱颖而出,更能提升你解决实际问题的能力。建议反复练习,理解每种算法背后的思想,而不仅仅是记住代码。编程之路漫漫,算法与数据结构是基石,祝你越走越远!

总结

到此这篇关于30个最常见算法题及其Java实现和详细解析的文章就介绍到这了,更多相关常见算法题Java实现内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java命名规范

    Java命名规范

    本文主要介绍了Java命名规范。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • Spring的RedisTemplate的json反序列泛型丢失问题解决

    Spring的RedisTemplate的json反序列泛型丢失问题解决

    本文主要介绍了Spring RedisTemplate中使用JSON序列化时泛型信息丢失的问题及其提出三种解决方案,可以根据性能需求选择方案,下面就来具体了解一下
    2025-07-07
  • 图书管理系统java版

    图书管理系统java版

    这篇文章主要为大家详细介绍了java版的图书管理系统,通过实例为大家快速掌握数据库编程技术,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • Java实现MySQL数据实时同步至Elasticsearch的方法详解

    Java实现MySQL数据实时同步至Elasticsearch的方法详解

    MySQL擅长事务处理,而Elasticsearch(ES)则专注于搜索与分析,将MySQL数据实时同步到ES,可以充分发挥两者的优势,下面我们就来看看如何使用Java实现这一功能吧
    2025-03-03
  • Maven版本依赖pom文件内容及使用剖析

    Maven版本依赖pom文件内容及使用剖析

    这篇文章主要为大家介绍了Maven版本依赖pom文件内容及使用剖析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • 分析ZooKeeper分布式锁的实现

    分析ZooKeeper分布式锁的实现

    在分布式的情况下,sychornized 和 Lock 已经不能满足我们的要求了,那么就需要使用第三方的锁了,这里我们就使用 ZooKeeper 来实现一个分布式锁
    2021-06-06
  • Spring Boot启动过程全面解析(三)

    Spring Boot启动过程全面解析(三)

    这篇文章主要介绍了Spring Boot启动过程全面解析(三)的相关资料,需要的朋友可以参考下
    2017-04-04
  • SpringBoot项目使用Log4j2+SLF4J构建日志的方法步骤

    SpringBoot项目使用Log4j2+SLF4J构建日志的方法步骤

    在现代软件开发中,日志记录是一个重要的部分,Spring Boot配置了多种日志框架,这篇文章主要介绍了SpringBoot项目使用Log4j2+SLF4J构建日志的方法步骤,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-11-11
  • 你真的理解Java中的ArrayList吗

    你真的理解Java中的ArrayList吗

    这篇文章主要给大家介绍了关于Java中ArrayList的相关资料,ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,需要的朋友可以参考下
    2021-08-08
  • SpringBoot自动配置Quartz的实现步骤

    SpringBoot自动配置Quartz的实现步骤

    本文主要介绍了SpringBoot自动配置Quartz的实现步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11

最新评论