第一周刷题总结
#leetcode
#数组的遍历
本周所做的数组类型题目大多是关于数组遍历,统计数组中的元素的。
一、 485 最大连续1的个数
题目详情:
给定一个二进制数组, 计算其中最大连续1的个数。
示例 :
输入: [1,1,0,1,1,1]
输出: 3
解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3.
int findMaxConsecutiveOnes(int* nums, int numsSize){
int max = 0,l = 0;//max保存最大连续1的个数,l负责动态地保存当前连续1的个数
int i;
for(i=0;i<numsSize;i++){//通过简单的一次遍历即可找到最后结果
if(nums[i]==1){
l++;
}else{
l = 0;
}
if(l>max){
max = l;
}
}
return max;
}
二、 495 提莫攻击
在《英雄联盟》的世界中,有一个叫 “提莫” 的英雄,他的攻击可以让敌方进入中毒状态。现在,给出提莫对艾希的攻击时间序列和提莫攻击的中毒持续时间,你需要输出艾希的中毒状态总时长。
示例:
输入: [1,4], 2
输出: 4
原因: 第 1 秒初,提莫开始对艾希进行攻击并使其立即中毒。中毒状态会维持 2 秒钟,直到第 2 秒末结束。
第 4 秒初,提莫再次攻击艾希,使得艾希获得另外 2 秒中毒时间。
所以最终输出 4 秒。
int findPoisonedDuration(int* timeSeries, int timeSeriesSize, int duration){
int count=0,i;
if(timeSeriesSize==0)
return 0;
for(i=0;i<timeSeriesSize-1;i++){
if(timeSeries[i]+duration<=timeSeries[i+1]){//当前攻击时间+持续时间还没超过下一次攻击时间
count += duration;
}else{
count += (timeSeries[i+1] -timeSeries[i]);//如果超过,计数就只加到下一次攻击开始时间
}
}
return count+duration;
}
三、 414 第三大的数
给定一个非空数组,返回此数组中第三大的数。如果不存在,则返回数组中最大的数。要求算法时间复杂度必须是O(n)。
示例 1:
输入: [3, 2, 1]
输出: 1
解释: 第三大的数是 1.
示例 2:
输入: [1, 2]
输出: 2
解释: 第三大的数不存在, 所以返回最大的数 2 .
*此题用到了三指针思想,在数组的遍历过程中,不断地将第一、第二、第三大的数进行替换,当在数组中找到了大于最大数的值,立即将第三大的数指向当前第二大的数,第二大的数指向当前第一大的数,第一大的数指向此时数组的值。同理,当此时数组中的值在第一第二大的数之间,将第三大的数指向当前第二大的数,第二大的数指向当前数组的值,第一大的数保持不变。
int thirdMax(int* nums, int numsSize){
long p = LONG_MIN, q = LONG_MIN, r = LONG_MIN; //初始时,将三个指针指向long取值范围内最小的值
if (numsSize == 1)
return nums[0];
else if (numsSize == 2)
return nums[0] > nums[1] ? nums[0] : nums[1];
for(int i=0;i<numsSize;i++){
if(nums[i]>p){
r = q;
q = p;
p = nums[i];
}else if(nums[i]<p && nums[i]>q){
r = q;
q = nums[i];
}else if(nums[i]<q && nums[i]>r){
r = nums[i];
}
}
if(r==LONG_MIN){ //遍历完后如果第三大的任没有赋值,返回第一大的数
return p;
}
return r;
}
四、 628 三个数的最大乘积
给定一个整型数组,在数组中找出由三个数组成的最大乘积,并输出这个乘积。
示例 1:
输入: [1,2,3]
输出: 6
示例 2:
输入: [1,2,3,4]
输出: 24
注意:数组中所有的元素范围是[-1000, 1000],是存在负数的。
*此题任然会用多指针思想求出数组中最大或最小的几个数,不同的是,前几大的数和前几小的数可以是相等的。最后结果1:两个最小的负数乘以一个最大的正数;结果2:三个最大的正数相乘,取其中较大者即可。
int maximumProduct(int* nums, int numsSize){
int p = 0, q = 0,i,sum1,sum2; //p、q分别指向第一、第二小的两个负数,初始为0
for(i=0;i<numsSize;i++){
if(nums[i]<p){
q = p;
p = nums[i];
}else if(nums[i]>=p && nums[i]<q){ //nums[i]和p之间必须有一个等号,即p、q是可以相等的,否则会产生错误。
//例如[-2,-2,1,2,3],如果p、q不可以相等,p=-2,q=0,结果为6,小于真实结果(-2)*(-2)*3 = 12
q = nums[i];
}
}
int a=p,b=p,c=p;
for(i=0;i<numsSize;i++){
if(nums[i]>=a){
c = b;
b = a;
a = nums[i];
}else if(nums[i]<a && nums[i]>=b){ //此处的等号十分重要
c = b;
b = nums[i];
}else if(nums[i]<b && nums[i]>c){
c = nums[i];
}
}
sum1 = p*q*a; //两个最小的负数乘以一个最大的数
sum2 = a*b*c; //三个最大的数相乘
return sum1>sum2 ? sum1 : sum2;
}