zoukankan      html  css  js  c++  java
  • 446等差数列划分II-子序列

    题目:如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。例如,以下数列为等差数列:
    1, 3, 5, 7, 9
    7, 7, 7, 7
    3, -1, -5, -9
    以下数列不是等差数列。
    1, 1, 2, 5, 7
    数组 A 包含 N 个数,且索引从 0 开始。该数组子序列将划分为整数序列 (P0, P1, ..., Pk),P 与 Q 是整数且满足 0 ≤ P0 < P1 < ... < Pk < N。如果序列 A[P0],A[P1],...,A[Pk-1],A[Pk] 是等差的,那么数组 A 的子序列 (P0,P1,…,PK) 称为等差序列。值得注意的是,这意味着 k ≥ 2。函数要返回数组 A 中所有等差子序列的个数。输入包含 N 个整数。每个整数都在 -231 和 231-1 之间,另外 0 ≤ N ≤ 1000。保证输出小于 231-1。

    来源:https://leetcode-cn.com/problems/arithmetic-slices-ii-subsequence/

    法一:自己的代码   时间复杂度是(1 + n) * n / 2 即n方

    思路:依次遍历A中的每个数,dp[i][k]表示以A[i]结尾公差为k(k != 0),长度至少为2的等差数列的个数-1,写dp转移方程之前,最重要的是要明确dp方程的定义。不同的dp转移方程直接决定了不同的方法。

    from collections import defaultdict
    from typing import List
    class Solution:
        def numberOfArithmeticSlices(self, A: List[int]) -> int:
            size = len(A)
            # 注意这里,内部是个可变对象,不能直接乘,类似与[[0,1]] * 5这种,改一个就全改了
            # dp = [defaultdict(lambda: -1)] * size
            dp = []
            # 生成dp
            for i in range(size):
                dp.append(defaultdict(lambda: -1))
            ans = 0
            for i in range(1,size):
                # m是为了记录公差为0的等差数列的长度
                m = 1
                for j in range(i):
                    # k是公差
                    k = A[i] - A[j]
                    # 如果公差存在于以A[j]结尾的数列中,且公差不为0,则必定可以构成长为3的等差数列
                    if k in dp[j].keys():
                        if k != 0:
                            # 这两行是关键,
                            # 注意这里的两个1,第一个1是为了补上dp[j][k]中从-1到0的那一次,同ans = ans + dp[j][k] + 1中的这个1
                            # 第二个1表示由A[j] A[i]构成的数列,同下面m +=1的这个1
                            dp[i][k] = (dp[j][k] + 1) +1 + dp[i][k]
                            # 加1是因为,初始值是从-1开始加的,如2:0表示公差为2,但它是长度为2的等差数列,
                            # 所以加1是为了抵消从-1加1到0的那一次,因为它已经构成了长度为2的等差数列,只不过以前长度无法达到3,现在达到了
                            # 这里之所以分开写是因为,dp[i][k]表示的是  以A[i]结尾的长度为2的等差数列的个数-1  所以dp[j][k]+1就是在A[j]后
                            # 添加A[i]后,以A[j] A[i]结尾的等差数列的个数
                            ans = ans + dp[j][k] + 1
                        else:
                            m += 1
                    else:
                        dp[i][k] += 1
                # 如果有公差为0的数列无法使用上述方法,直接记录数列的长度用归纳法求解
                ans += (2 ** m - (m+1))
            # for i in dp:
            #     print(i)
            print(len(A), len(set(A)))
            return ans
    if __name__  == '__main__':
        duixiang = Solution()
        # a = duixiang.numberOfArithmeticSlices([1,1,1,1,1])
        # a = duixiang.numberOfArithmeticSlices([79,20,64,28,67,81,60,58,97,85,92,96,82,89,46,50,15,
        #                                            2,36,44,54,2,90,37,7,79,26,40,34,67,64,28,60,89,46,
        #                                            31,9,95,43,19,47,64,48,95,80,31,47,19,72,99,28,46,
        #                                            13,9,64,4,68,74,50,28,69,94,93,3,80,78,23,80,43,49,
        #                                            77,18,68,28,13,61,34,44,80,70,55,85,0,37,93,40,47,
        #                                            47,45,23,26,74,45,67,34,20,33,71,48,96])
        # a = duixiang.numberOfArithmeticSlices([2,2,-1,2,5,8])
        # a = duixiang.numberOfArithmeticSlices([1,2,3,4,5])
        # a = duixiang.numberOfArithmeticSlices([6,6,8,10])
        a = duixiang.numberOfArithmeticSlices([4,4,3,4,5,6])
        # a = duixiang.numberOfArithmeticSlices([3,4,5,6,7])
        print(a)
    View Code
  • 相关阅读:
    iOS图片拉伸技巧
    Swift和OC混合使用
    【转】动态计算UITableViewCell高度详解
    AutoLayout~Label
    【转】初探 iOS8 中的 Size Class
    Objective-C runtime~
    [转]Objective-C中的类和对象(instance)
    Masonry~
    [转] ios学习--openURL的使用方法
    Autolayout~代码实现
  • 原文地址:https://www.cnblogs.com/xxswkl/p/12295923.html
Copyright © 2011-2022 走看看