力扣(LeetCode) 【每日一题】 413.等差数列划分 2021.8.10

题目链接:

413.等差数列划分

不想戳的看下图:

在这里插入图片描述

示例:

在这里插入图片描述

提示:

在这里插入图片描述

解题思路1:

双指针

1:先求出所有满足等差要求的最长连续子数组。
2:在最长子数组中,找出所有满足要求的连续分子数组,其数量和即为所求值。

代码如下:

class Solution {
    public int numberOfArithmeticSlices(int[] nums) {
    	int result = 0;
	if (nums.length < 3) {
		return result;
	}
	//求所有最长连续子数组
	List<int[]> sonMaxLongList = new ArrayList<>();
	int start = 0;
	int end = 0;
	for (int i = 0; i < nums.length - 2; i++) {
		int a = nums[i];
		int b = nums[i + 1];
		int c = nums[i + 2];
		//满足条件,则结尾指针指向i+2
		if ((b * 2) == (a + c)) {
			end = i + 2;
			//如果结尾是数组末尾,压入
			if (end == nums.length - 1) {
				sonMaxLongList.add(new int[]{start, end});
			}
		} else {
			//不满足条件,有两种情况,一种是前面有满足条件的最长子数组、一种是都不满足
			if(end-start >= 2){
				//满足条件压入,并将开始指针置于结尾。i指针直接跳到结尾前一位。
				sonMaxLongList.add(new int[]{start, end});
				start = end;
				i = start-1;
			}else{
				start = i + 1;//开始指针指向下一个循环值
			}
		}
	}
	//找到所有满足条件的子数组可能
	if(sonMaxLongList.size() != 0){
		for(int[] son : sonMaxLongList){
			result += getNumberOfArithmeticSlicesTimes(son[0], son[1]);
		}
	}
	return result;
    }

    public int getNumberOfArithmeticSlicesTimes(int start, int end) {
		int times = 0;
		for (int i = start; i <= end-2; i++) {
			for(int j = i+2; j <= end; j++){
				times++;
			}
		}
		return times;
	}
}

解题思路2:

动态规划(dp)

状态:dp[i] 表示以 nums[i] 结尾的数组可以组成等差数列的个数,并不一定以 nums[0] 开头。
状态转移方程:dp[i] = dp[i-1]+1 if nums[i]-nums[i-1]==nums[i-1]-nums[i-2] else 0
可以理解为:
1、若之前的dp不为0,且当前nums[i]符合条件,则说明此 nums[i] 与前面以nums[i-1]结尾的等差序列是连续的(有相同的差值)。假设连续的等差序列第一个数为num[a],则以nums[i-1]结尾的等差数列,均可以换为以nums[i]结尾,这就等于dp[n-1]的值,而加一是因为nums[i]的引入又增加了nums[a]至nums[i]这个等差数列
2、若dp为0,则说明之前并没有以nums[i-1]结尾的等差序列存在,此时以nums[i]结尾的是新的等差数列,所以就是1。
3、若条件不满足,则说明此时的nums[i]不连续,与之前的等差数列存在间隙,所以为0,表示以nums[i]为结尾的等差数列个数为0
最后将所有的dp加起来就是ans。

代码如下:

class Solution {
    public int numberOfArithmeticSlices(int[] nums) {
        int len = nums.length;
        int[] dp = new int[len];
        for(int i=2; i<len; i++){
            if(nums[i]-nums[i-1] == nums[i-1]-nums[i-2]){
                dp[i] = dp[i-1] + 1;
            }else{
                dp[i] = 0;
            }
        }
        int ans = 0;
        for(int i=0; i<len; i++){
            ans += dp[i];
        }
        return ans;
    }
}

小结

两种方法都比较简单,而且速度都很快,都是好方法。若同学们有更好的方法请私我,谢谢谢谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值