31.下一个排列

题目描述

题目描述

思路

思路

代码

java 复制代码
class Solution {
    public void nextPermutation(int[] nums) {
        int i = nums.length - 2;
        
        // 1. 从后往前找第一个相邻的升序对 (nums[i] < nums[i+1])
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        
        // 如果 i >= 0,说明找到了这样的数字,需要进行交换
        // 如果 i < 0,说明整个数组是降序的,直接跳过交换步骤,进行全部反转即可
        if (i >= 0) {
            int j = nums.length - 1;
            // 2. 从后往前找第一个大于 nums[i] 的数字 nums[j]
            while (j > i && nums[j] <= nums[i]) {
                j--;
            }
            // 3. 交换 nums[i] 和 nums[j]
            swap(nums, i, j);
        }
        
        // 4. 将 i 之后的序列反转,使其变为升序(字典序最小)
        reverse(nums, i + 1);
    }
    
    // 辅助方法:交换数组中两个元素
    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
    
    // 辅助方法:反转数组中从 start 开始到末尾的部分
    private void reverse(int[] nums, int start) {
        int left = start, right = nums.length - 1;
        while (left < right) {
            swap(nums, left, right);
            left++;
            right--;
        }
    }
}

复杂度分析

  • 时间复杂度:O(N)O(N)O(N),其中 NNN 是数组的长度。我们最多只需要遍历数组两次(一次找 i,一次找 j),然后再反转一次数组末尾部分
  • 空间复杂度:O(1)O(1)O(1),我们所有的交换和反转操作都是在原数组上直接进行的(原地修改),只使用了几个额外的整型变量,完全符合题意
相关推荐
To_OC39 分钟前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode
小bo波4 小时前
使用Thread子类创建线程 VS 使用Runnable接口创建线程的区别
java·多线程·thread·并发编程·runnable
SamDeepThinking5 小时前
高并发场景下,CompletableFuture与ForkJoinPool该如何取舍?
java·后端·面试
用户938515635076 小时前
从 O(n²) 到 O(nlogn):一文读懂快速排序的“快”与“妙”
javascript·算法
To_OC7 小时前
手写快排次次翻车?别死背快排模板了,这才是面试官想听的底层逻辑
javascript·算法·排序算法
饼干哥哥8 小时前
Reddit VOC调研太慢?搭一个AI专家团队半小时洞察任何品类|以猫用饮水机为例
人工智能·算法·ai编程
张不才8 小时前
CPU 100% 了怎么办?Java 性能排障的标准化操作
java·后端
地平线开发者9 小时前
Transformer模型部署之性能优化指南
算法
地平线开发者9 小时前
人在途中:从“编译失败”到“模型可落地”——CUDA 自定义算子
算法·自动驾驶
shepherd1119 小时前
吞吐量提升 10 倍:高并发大批量数据处理任务的架构演进与性能调优
java·后端·架构