算法实战笔记: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),仅使用两个指针变量,常数额外空间。

三、两道题面试重点总结

表格

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

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

相关推荐
wangcheng3037 分钟前
关键词优化怎么理解最清楚
笔记
渣渣苏15 分钟前
硬核拆解 HNSW:亿级向量如何实现毫秒级召回?(上篇)
人工智能·算法·支持向量机·ai·向量数据库·hnsw·智能体
如竟没有火炬16 分钟前
字符串相乘——int数组转字符串
开发语言·数据结构·python·算法·leetcode·深度优先
吃好睡好便好19 分钟前
在Matlab中绘制三维等高线图
开发语言·python·学习·算法·matlab·信息可视化
项目申报小狂人29 分钟前
一种使用双向长短时记忆网络结合鲸鱼优化算法的类火星矿物元素精确定量分析模型
人工智能·算法·lstm
wangjialelele34 分钟前
【SystemV】基于建造者模式的信号量
linux·c语言·c++·算法·建造者模式
土星碎冰机1 小时前
ai自学笔记(3.安卓篇,制作app
android·笔记·ai
Aaron15881 小时前
RFSOC+VU13P/VU9P+GPU多通道同步一体化解决方案
人工智能·嵌入式硬件·算法·matlab·fpga开发·硬件架构·基带工程
土星碎冰机1 小时前
ai自学笔记 (2.prompt 踩坑与优化)
笔记·ai·prompt·claude
pluviophile_s2 小时前
数据结构:第1讲:算法分析
数据结构·笔记