日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

【LeetCode笔记】31. 下一个排列(Java、原地算法、偏数学)

發(fā)布時間:2024/7/23 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【LeetCode笔记】31. 下一个排列(Java、原地算法、偏数学) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 題目描述
  • 思路 && 代碼
      • 二刷

打卡第八天~

題目描述

  • 需要花點(diǎn)時間思考的一道題,這篇題解寫得很好。

思路 && 代碼

  • 主要分為這三個步驟:
  • 從后往前找到滿足 nums[first] < nums[first + 1] 的索引 first
  • 從后往前找到滿足 nums[second] > nums[first] 的索引 second
  • 交換 nums[first]、nums[second],翻轉(zhuǎn) nums[ first + 1 : ]
  • 對于步驟1,找不到 first 時翻轉(zhuǎn)整個數(shù)組,也就是當(dāng)前排列為最大排列的情況。
  • 對于步驟2,nums[second] 一定是最接近 nums[first] 的值(可以證明)
  • 步驟3進(jìn)行交換后,有 nums[first + 1 : ] 滿足 nums[i] > nums[i + 1],即當(dāng)前排列為nums[first + 1 : ] 的最大排列;那么對nums[first : ]進(jìn)行一個翻轉(zhuǎn),即可得到 nums[first : ]的最小排列,也就是最接近初始排列的下一個排列。
  • 借用leetcode 題解區(qū) powcai 大佬的例子
  • 對于 nums = [1, 2, 7, 4, 3, 1]
  • 找到 nums[first] = nums[1] = 2
  • 找到 nums[second] = nums[4] = 3
  • 交換 nums = [1, 3, 7, 4, 2, 1](可以看到 7 4 2 1 是剛好降序排列的)
  • 翻轉(zhuǎn) nums = [1, 3, (1, 2, 4, 7)] (剛好變成 1, 3 開頭的最小排列,是1, 2 排列的最大排列的下一個排列)
  • 復(fù)雜度 O(n) 、O(1),很有意思的一道題,可以多看看~
class Solution {public void nextPermutation(int[] nums) {// Case 1: 空數(shù)組 or 無元素if(nums == null || nums.length == 0) {return; }// 1. 先找最大索引 k,滿足 nums[k] < nums[k + 1];不存在則翻轉(zhuǎn)整個數(shù)組int firstIndex = -1;int len = nums.length;// 從后往前找for(int i = len - 2; i >= 0; i--) {if(nums[i] < nums[i + 1]) {firstIndex = i;break;}}// Case 2: 找不到的情況,直接翻轉(zhuǎn)數(shù)組(即本就是最大排列)if(firstIndex == -1) {reverse(nums, 0, len - 1);return;}// 2. 然后找到第二個最大索引:滿足 nums[sec] > nums[first]int secondIndex = -1;// 同樣是從后往前找,找到的第一個肯定是最接近 nums[first]的值for(int i = len - 1; i >= 0; i--) {if(nums[i] > nums[firstIndex]) {secondIndex = i;break;}}// 3. 先交換 first 和 second(交換后,當(dāng)前序列為nums[first : second]的最大序列)swap(nums, firstIndex, secondIndex);// 4. 然后對 nums[first + 1 :] 進(jìn)行翻轉(zhuǎn)(翻轉(zhuǎn)后,當(dāng)前序列為nums[first : second]的最小序列)reverse(nums, firstIndex + 1, len - 1);}// 翻轉(zhuǎn)函數(shù)public void reverse(int[] nums, int i, int j) {while(i < j) {swap(nums, i++, j--);}}// 交換函數(shù)public void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;} }

二刷

  • keywords:兩個下標(biāo)、交換、翻轉(zhuǎn)
  • firstIndex:第一個與后面的元素交換,能讓排列變大的元素
  • 交換:讓排列變大
  • 翻轉(zhuǎn):在大于初始排列的情況下,讓排列變得最小。
class Solution {public void nextPermutation(int[] nums) {int firstIndex = nums.length;for(int i = nums.length - 2; i >= 0; i--) {if(nums[i] < nums[i + 1]) {firstIndex = i;break;}}if(firstIndex == nums.length) {reverse(nums, 0, nums.length - 1);return;}int secondIndex = nums.length;for(int i = nums.length - 1; i >= 0; i--) {if(nums[i] > nums[firstIndex]) {secondIndex = i;swap(nums, firstIndex, secondIndex);break;}}reverse(nums, firstIndex + 1, nums.length - 1);}void reverse(int[] nums, int left, int right) {while(left < right) {swap(nums, left++, right--);}}void swap(int[] nums, int left, int right) {int temp = nums[left];nums[left] = nums[right];nums[right] = temp;} }

總結(jié)

以上是生活随笔為你收集整理的【LeetCode笔记】31. 下一个排列(Java、原地算法、偏数学)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。