PS:算法并非原创,仅作个人学习记录使用,侵删。
题目描述
算法分析
个人的思路是:遍历一遍数组,对每一个递增段进行长度计数,结束时将当前递增段长度结果和已知的最长序列长度进行比较,不断维护更新已知最长序列长度,遍历完成后得出结果。
这种做法也是最容易理解和想到的想法。
此外,还有双指针法【C++实现】、贪心法【java实现】、动态规划法【python实现】。
其中,贪心法利用双指针,每轮遍历都会维护最终结果,其性能是上述几种算法中最好的。
代码实现
【C】
/*
该思路也就是“算法分析”中的个人思路。
遍历一遍数组,对每一个递增段进行长度计数,结束时将当前递增段长度结果和已知的最长序列长度进行比较,不断维护更新已知最长序列长度,遍历完成后得出结果。
*/
int findLengthOfLCIS(int* nums, int numsSize){
//特殊情况考虑
if(numsSize == 0)//数组长度为0,数组为空
return 0;
if(numsSize == 1)//数组长度为1
return 1;
//一般情况
int length = 1;//每个递增序列段的计数变量
int ans = 1;//最长的递增序列长度
for(int i = 0; i < numsSize - 1; i++){//遍历数组元素
if(nums[i] < nums[i+1])//每个连续递增序列持续计数
length++;
else//如果不再连续,重置length值用于下一次遍历
length = 1;
if(length > ans)//最终结果的维护更新
ans = length;
}
return ans;
}
【C++】
/*
思路基本上和C语言代码的思路一致。但是使用了双指针解法,更加精妙。
每次遍历某段时,开始指针为i,结束指针为j,两者之差为该段序列的长度
*/
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
int n = nums.size(), ans = 0;//n为数组长度,ans为最终结果
for(int i=0, j=0; i<n; i=j){//遍历一遍数组,i为每段序列开始长度,j为每段序列结束长度。
while(++j<n && nums[j]>nums[j-1]);//在连续递增序列中移动指针。
ans = max(ans, j-i);//j-i表示当前连续递增序列的长度,ans为最终结果,这里是对最大值的维护更新
}
return ans;
}
};
【Java】
/*
官方题解:贪心算法
也用到了双指针,和C++与C的大体思想一致,但是贪心算法体现在每次遍历元素都在维护最大值,而不是每段维护一次。这样就能确保求解的一定是最大值。
这种算法理解起来不够直观,但是时间性能上还是很不错的,C与C++均花了12ms,而Java只花了2ms
*/
class Solution {
public int findLengthOfLCIS(int[] nums) {
int ans = 0;//最终结果
int n = nums.length;//数组长度
int start = 0;//开始指针
for (int i = 0; i < n; i++) {//i为结束指针
if (i > 0 && nums[i] <= nums[i - 1]) {//如果递增序列结束,开始指针和结束指针取相同
start = i;
}
//如果递增序列未结束,那么每次都会计算序列长度,进行结果维护。
ans = Math.max(ans, i - start + 1);//结果维护每轮遍历都会进行
}
return ans;
}
}
【python】
#动态规划
#方程为:dp[i]={dp[i-1]+1 第[i]个元素和第[i-1]个元素之间递增
# {1 第[i]个元素和第[i-1]个元素之间不递增
#用一个数组存储所有结果
class Solution:
def findLengthOfLCIS(self, nums):
n=len(nums)#数组长度
if not nums or n<0:#特殊情况考虑
return 0
dp=[1]*n#dp是结果数组,dp[i]存储i个元素所在段的递增数组长度
for i in range(1,n):#遍历一遍数组
if nums[i]>nums[i-1]:
#如果递增,那么第i个结果就是第i-1个结果+1;
#如果不再递增,那么第i个结果默认为1
dp[i]=dp[i-1]+1
return max(dp)#返回最大值