算法实战笔记:LeetCode 31 下一个排列 & 287 寻找重复数

目录

[一、LeetCode 31 下一个排列](#一、LeetCode 31 下一个排列)

题目描述

核心思路(三步法)

[Java 完整代码](#Java 完整代码)

复杂度分析

[二、LeetCode 287 寻找重复数](#二、LeetCode 287 寻找重复数)

题目描述

核心思路(快慢指针法,弗洛伊德龟兔赛跑)

[Java 完整代码](#Java 完整代码)

复杂度分析

三、两道题面试重点总结


今天给大家分享两道面试高频中等题:31. 下一个排列287. 寻找重复数,两道题都有非常经典的最优解法,掌握后对面试和算法思维提升都很有帮助。


一、LeetCode 31 下一个排列

题目描述

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。必须原地修改,只允许使用额外常数空间。

核心思路(三步法)

这道题的核心是找到字典序的下一个排列,有固定的三步流程:

  1. 从后向前找 "下降点" :找到第一个满足 nums[i] < nums[i+1] 的位置 i,这是排列中需要被替换的 "较小数"。
  2. 从后向前找 "替换数" :找到第一个比 nums[i] 大的数 nums[j],交换 nums[i]nums[j]
  3. 反转尾部升序序列 :交换后,i 之后的序列是降序的,反转它就能得到最小的尾部,从而形成下一个排列。

Java 完整代码

java

运行

复制代码
public class NextPermutation {
    public void nextPermutation(int[] nums) {
        if (nums == null || nums.length <= 1) {
            return;
        }

        // 1. 从后向前找第一个 nums[i] < nums[i+1] 的位置
        int i = nums.length - 2;
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }

        if (i >= 0) {
            // 2. 从后向前找第一个比 nums[i] 大的数,交换
            int j = nums.length - 1;
            while (nums[j] <= nums[i]) {
                j--;
            }
            swap(nums, i, j);
        }

        // 3. 反转 i 之后的部分(升序排列)
        reverse(nums, i + 1, nums.length - 1);
    }

    // 交换数组中两个元素
    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    // 反转数组指定区间
    private void reverse(int[] nums, int left, int right) {
        while (left < right) {
            swap(nums, left, right);
            left++;
            right--;
        }
    }

    // 测试主函数
    public static void main(String[] args) {
        NextPermutation solution = new NextPermutation();
        int[] nums1 = {1, 2, 3};
        solution.nextPermutation(nums1);
        printArray(nums1); // 输出:1 3 2

        int[] nums2 = {3, 2, 1};
        solution.nextPermutation(nums2);
        printArray(nums2); // 输出:1 2 3
    }

    private static void printArray(int[] nums) {
        for (int num : nums) {
            System.out.print(num + " ");
        }
        System.out.println();
    }
}

复杂度分析

  • 时间复杂度:O (n),最多遍历两次数组,反转一次数组。
  • 空间复杂度:O (1),原地修改,仅使用常数额外空间。

二、LeetCode 287 寻找重复数

题目描述

给定一个包含 n + 1 个整数的数组 nums,其数字都在 [1, n] 范围内(包括 1n),可知至少存在一个重复的整数。假设 nums 只有一个重复的整数,返回这个重复的数。必须解决问题且不修改数组 nums 且只使用额外常数级别的空间。

核心思路(快慢指针法,弗洛伊德龟兔赛跑)

这道题可以转化为寻找链表环的入口节点问题:

  • 把数组看作一个链表,数组的索引是节点,数组的值是下一个节点的索引。
  • 因为存在重复数,链表中必然存在环,重复数就是环的入口节点。
  • 使用快慢指针:快指针每次走两步,慢指针每次走一步,两者相遇后,再让快指针从头开始走,每次走一步,和慢指针再次相遇的节点就是环的入口(重复数)。

Java 完整代码

java

运行

复制代码
public class FindDuplicate {
    public int findDuplicate(int[] nums) {
        // 快慢指针初始化
        int slow = 0;
        int fast = 0;

        // 第一次相遇
        do {
            slow = nums[slow];
            fast = nums[nums[fast]];
        } while (slow != fast);

        // 快指针回到起点,再次相遇即为环入口
        fast = 0;
        while (slow != fast) {
            slow = nums[slow];
            fast = nums[fast];
        }

        return slow;
    }

    // 测试主函数
    public static void main(String[] args) {
        FindDuplicate solution = new FindDuplicate();
        int[] nums1 = {1, 3, 4, 2, 2};
        System.out.println("重复数是:" + solution.findDuplicate(nums1)); // 输出:2

        int[] nums2 = {3, 1, 3, 4, 2};
        System.out.println("重复数是:" + solution.findDuplicate(nums2)); // 输出:3
    }
}

复杂度分析

  • 时间复杂度:O (n),快慢指针在链表中移动的总步数是线性的。
  • 空间复杂度:O (1),仅使用两个指针变量,常数额外空间。

三、两道题面试重点总结

表格

题目 核心考点 关键技巧 易错点
下一个排列 字典序排列、原地算法 三步法(找下降点→交换→反转) 边界处理(完全降序的情况)、反转区间的起点
寻找重复数 数组与链表转化、快慢指针 弗洛伊德龟兔赛跑算法 循环条件的设置、两次相遇的逻辑

这两道题都是面试中非常经典的 "中等题天花板",掌握它们不仅能应对面试,还能锻炼对数组、链表和原地算法的理解。

相关推荐
穿条秋裤到处跑2 小时前
每日一道leetcode(2026.04.24):距离原点最远的点
算法·leetcode·职场和发展
就叫飞六吧2 小时前
基于googleshell下载文件/资源
笔记
wayz112 小时前
Day 13 编程实战:朴素贝叶斯与极端涨跌预警
人工智能·算法·机器学习
踩坑记录2 小时前
121. 买卖股票的最佳时机 easy 贪心算法
leetcode
lwf0061642 小时前
逻辑回归学习笔记-数学直接解回归方程
笔记·学习·逻辑回归
叶小鸡2 小时前
小鸡玩算法-力扣HOT100-贪心算法
算法·leetcode·贪心算法
Old Uncle Tom2 小时前
提示词编写规范
数据库·算法
火山口车神丶2 小时前
如何借助AI进行模块封装DIY
javascript·人工智能·算法
MegaDataFlowers2 小时前
15.三数之和
算法