日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

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

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

文章目錄

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

打卡第八天~

題目描述

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

思路 && 代碼

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

二刷

  • keywords:兩個下標、交換、翻轉
  • firstIndex:第一個與后面的元素交換,能讓排列變大的元素
  • 交換:讓排列變大
  • 翻轉:在大于初始排列的情況下,讓排列變得最小
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;} }

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。