本文属于「征服LeetCode」系列文章之一这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁本系列将至少持续到刷完所有无锁题之日为止由于LeetCode还在不断地创建新题本系列的终止日期可能是永远。在这一系列刷题文章中我不仅会讲解多种解题思路及其优化还会用多种编程语言实现题解涉及到通用解法时更将归纳总结出相应的算法模板。为了方便在PC上运行调试、分享代码文件我还建立了相关的仓库https://github.com/memcpy0/LeetCode-Conquest。在这一仓库中你不仅可以看到LeetCode原题链接、题解代码、题解文章链接、同类题目归纳、通用解法总结等还可以看到原题出现频率和相关企业等重要信息。如果有其他优选题解还可以一同分享给他人。由于本系列文章的内容随时可能发生更新变动欢迎关注和收藏征服LeetCode系列文章目录一文以作备忘。给你一个数组nums。nums的源数组中所有元素与nums相同但按非递减顺序排列。如果nums能够由源数组轮转若干位置包括 0 个位置得到则返回true否则返回false。源数组中可能存在重复项。注意数组A在轮转x个位置后得到长度相同的数组B使得对于每一个有效的下标i满足B[i] A[(ix) % A.length]。示例 1输入nums[3,4,5,1,2]输出true解释[1,2,3,4,5]为有序的源数组。 可以轮转 x2个位置使新数组从值为3的元素开始[3,4,5,1,2]。示例 2输入nums[2,1,3,4]输出false解释源数组无法经轮转得到 nums 。示例 3输入nums[1,2,3]输出true解释[1,2,3]为有序的源数组。 可以轮转 x0个位置即不轮转得到 nums 。提示1 nums.length 1001 nums[i] 100方法 至多一次严格递减根据题意如果n u m s numsnums是由一个递增数组旋转得到那么n u m s numsnums至多有两个递增段。即n u m s numsnums至多有一对相邻元素是严格递减的即n u m s [ i − 1 ] n u m s [ i ] nums[i - 1] nums[i]nums[i−1]nums[i]至多出现一次。此外如果有两个递增段第二段的最大值不能超过第一段的最小值即n u m s [ 0 ] ≥ n u m s [ n − 1 ] nums[0]\ge nums[n-1]nums[0]≥nums[n−1]。写法一如下classSolution{publicbooleancheck(int[]nums){intnnums.length;booleansortedtrue;for(inti1;in;i){if(nums[i-1]nums[i]){// 严格递减if(!sorted){// 之前出现过严格递减说明至少有三个递增段returnfalse;}sortedfalse;// 标记遇到了严格递减}}returnsorted||nums[0]nums[n-1];}}classSolution{public:boolcheck(vectorintnums){intnnums.size();boolsortedtrue;for(inti1;in;i){if(nums[i-1]nums[i]){// 严格递减if(!sorted){// 之前出现过严格递减说明至少有三个递增段returnfalse;}sortedfalse;// 标记遇到了严格递减}}returnsorted||nums[0]nums[n-1];}};classSolution:defcheck(self,nums:list[int])-bool:is_sortedTrueforx,yinpairwise(nums):ifxy:# 严格递减ifnotis_sorted:# 之前出现过严格递减说明至少有三个递增段returnFalseis_sortedFalse# 标记遇到了严格递减returnis_sortedornums[0]nums[-1]funccheck(nums[]int)bool{n:len(nums)sorted:truefori:1;in;i{ifnums[i-1]nums[i]{// 严格递减if!sorted{// 之前出现过严格递减说明至少有三个递增段returnfalse}sortedfalse// 标记遇到了严格递减}}returnsorted||nums[0]nums[n-1]}写法二如下提前判断n u m s [ 0 ] ≥ n u m s [ n − 1 ] nums[0] \ge nums[n - 1]nums[0]≥nums[n−1]。classSolution{publicbooleancheck(int[]nums){intnnums.length;booleansortednums[0]nums[n-1];for(inti1;in;i){if(nums[i-1]nums[i]){// 严格递减if(!sorted){// 之前出现过严格递减说明至少有三个递增段returnfalse;}sortedfalse;// 标记遇到了严格递减}}returntrue;}}classSolution{public:boolcheck(vectorintnums){intnnums.size();boolsortednums[0]nums[n-1];for(inti1;in;i){if(nums[i-1]nums[i]){// 严格递减if(!sorted){// 之前出现过严格递减说明至少有三个递增段returnfalse;}sortedfalse;// 标记遇到了严格递减}}returntrue;}};classSolution:defcheck(self,nums:list[int])-bool:is_sortednums[0]nums[-1]forx,yinpairwise(nums):ifxy:# 严格递减ifnotis_sorted:# 之前出现过严格递减说明至少有三个递增段returnFalseis_sortedFalse# 标记遇到了严格递减returnTruefunccheck(nums[]int)bool{n:len(nums)sorted:nums[0]nums[n-1]fori:1;in;i{ifnums[i-1]nums[i]{// 严格递减if!sorted{// 之前出现过严格递减说明至少有三个递增段returnfalse}sortedfalse// 标记遇到了严格递减}}returntrue}复杂度分析时间复杂度O ( n ) O(n)O(n)其中n nn是n u m s numsnums的长度。空间复杂度O ( 1 ) O(1)O(1)。思考题1、在n u m s numsnums中找到一个最长的连续子数组a aa满足a aa是由一个递增数组旋转得到的。答可以使用变长滑动窗口用一个变量记录当前窗口内下降点的数量。2、输入q u e r i e s queriesqueries对于每个q u e r i e s [ i ] [ l i , r i ] queries[i][l_i ,r_i]queries[i][li​,ri​]判断n u m s numsnums的连续子数组[ l i , r i ] [l_i, r_i][li​,ri​]是否由一个递增数组旋转得到。答每次查询都遍历则时间复杂度过高。可以预处理前缀和来达到O ( 1 ) O(1)O(1)的单次查询效果。做法是用一个数组记录所有局部下降点n u m s [ i − 1 ] n u m s [ i ] nums[i-1] nums[i]nums[i−1]nums[i]则i ii为下降点并用前缀和统计区间[ l 1 , r ] [l1, r][l1,r]内的下降点总数为0 00则必然满足题意为1 11且左端点≥ \ge≥右端点也满足题意≥ 2 \ge 2≥2则一定不满足。