LeetCode第31题:"下一个排列" C#篇
理解题意:
这道题大概的意思是,将nums数组换一个排列方式,但要求比当前排列要大并且是当前数组大的排列中最小的一种排列
思路:
相信很多人看到这题第一个会想到的思路是,我只需要将这个数组所有比当前数组大的排列都整理出来,再选出最小的那一个排列,此题可解
很显然啊....这不是一个标准的答案,这个思路的时间复杂度是O(n!) 也就是n的阶乘,拿示例1举例n=3那么就是1*2*3=6,假设n=100或者1000或者更高 所以....嗯....额你懂的对吧
我们应该可以把这个时间复杂度优化到O(N),请各位观察下这两组数字
54321(排列前)
12345(排列后)
从上面数字中,我们看到单调递减的数字是无法得到这个解的,题目中的示例2也是如此,由此推测,正确答案是不是和单调递减有关系呢?
请再看下面这个示例
24534421(排列前)
24541234(排列后)
会发现我们从右往前数,我找到那位破坏单调递增的数字,再找到比这个数字大中最小的那个数字(注意是要靠后),交换位置,并将后面的数字升序排序即可
这里解释一下,为什么要从右往前数,因为调换越后面的数字,整个排列变化的值越小,这样是离正确答案最近的一条选项,请看下面例子
64564353(排列前)
64564533(排列后)
总结一下逻辑思路:
代码:
1 /// <summary> 2 /// 下一个排列 3 /// </summary> 4 /// <param name="nums"></param> 5 /// <returns></returns> 6 public static int[] NextArrangement(int[] nums) 7 { 8 //如果数组为空或只有一个元素,则无法进行下一个排列 9 int len = nums.Length; 10 if (len==1) 11 { 12 return nums; 13 } 14 15 //从右向左找到第一个降序的元素 16 int i = len - 2; 17 while (i >= 0 && nums[i] >= nums[i + 1]) 18 { 19 i--; 20 } 21 22 //如果数组已经是降序排列,则无法进行下一个排列 23 if (i<0) 24 { 25 reverse(nums, 0, len - 1); 26 return nums; 27 } 28 29 //从右向左找到第一个大于nums[i]的元素 30 int nextGreaterIndex = i + 1; 31 while (nextGreaterIndex < len && nums[nextGreaterIndex] >nums[i]) 32 { 33 nextGreaterIndex++; 34 } 35 36 //交换nums[i]和nums[nextGreaterIndex-1] 37 swap(nums, i, nextGreaterIndex - 1); 38 //将nums[i+1]到nums[len-1]进行反转 39 reverse(nums, i + 1, len - 1); 41 return nums; 42 } 43 44 /// <summary> 45 /// 交换数组中的两个元素 46 /// </summary> 47 /// <param name="nums"></param> 48 /// <param name="i">开始下标</param> 49 /// <param name="j">结束下标</param> 50 private static void swap(int[] nums, int i, int j) 51 { 52 int temp = nums[i]; 53 nums[i] = nums[j]; 54 nums[j] = temp; 55 } 56 57 /// <summary> 58 /// 反转数组中的元素 59 /// </summary> 60 /// <param name="nums">数组</param> 61 /// <param name="start">开始下标</param> 62 /// <param name="end">结束下标</param> 63 public static void reverse(int[] nums, int start, int end) 64 { 65 while (start < end) 66 { 67 swap(nums, start++, end--); 68 } 69 }
使用:
1 #region 下一个排序 2 //int[] nums = new int[] { 2, 4, 5, 3, 4, 4, 2, 1 }; 3 int[] nums = new int[] { 6, 4, 5, 6, 4, 3, 5, 3 }; 4 for (int i = 0; i < nums.Length; i++) 5 { 6 Console.Write(nums[i]); 7 } 8 Console.WriteLine(""); 9 var result=Calculation.NextArrangement(nums); 10 for (int i = 0; i < result.Length; i++) 11 { 12 Console.Write(result[i]); 13 } 14 Console.Read(); 15 #endregion
结果:
时间复杂度优化解析:
希望此篇文章对你有帮助,有更有的方法或者不太清楚有疑惑的地方也非常欢迎留言私信,当然啦,如果可以给威某人点一个小小的赞就更好啦哈哈 ,下篇再见,各位家人~
本文来自博客园,作者:echo_sw,转载请注明原文链接:https://www.cnblogs.com/shenweif/p/18571757