lintcode 617 Maximum Average Subarray

博客围绕lintcode 617最大平均子数组问题展开,虽未给出具体内容,但可推测是关于该问题的分析、解法等信息技术相关探讨。

 

617Maximum Average Subarray长度大于等于k的连续元素的最大平均值,比leet643再多加一个局部最大ll, l变化起点, ll变化终点。

 

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Feb 14 15:41:08 2018

@author: vicky
"""
#法1:o(n2)
class Solution:
    """
    @param: nums: an array with positive and negative numbers
    @param: k: an integer
    @return: the maximum average
    """
    def maxAverage(self, nums, k):
        # write your code here
        g=sum(nums[0:k])/k
        l=sum(nums[0:k])/k
        for i in range(len(nums)-k):
            ll=l #l变换数组开头,ll变换数组末尾
            for j in range(i+k,len(nums)):
                ll=(ll*(j-i)+nums[j])/(j-i+1) #ll=从i开始的大于k个数字的平均值
                g=max(g,ll)
            l=(l*k-nums[i]+nums[k+i])/k #l=从i开始的k个数字的平均值
        g=max(g,l)
        return g

nums=[1,12,-5,-6,50,3]
k=3
print(Solution().maxAverage(nums,k))


二分法:
第一类: 需查找和目标值完全相等的数
eg:数组nums=[2, 4, 5, 6, 9],target = 6,需要返回3
#left,right,mid都是数组index
    left=0
    right=len(nums)
    while left<right:
        mid=(right+left)/2
        if nums[mid] == target: 
            return mid
        elif nums[mid] < target: 
            left=mid #target在右区间则舍去左区间
        else:
            right=mid #target在左区间则舍去右区间
        
第二类:查找第一个不小于目标值的数
有时候要查找的目标值不一定会在数组中出现,也有可能是跟目标值相等的数在数组中并不唯一,而是有多个,
那么这种情况下nums[mid] == target这条判断语句就没有必要存在。
eg:在数组nums=[2,4,5,5,6]中查找数字5,就会返回数字5的位置3
    left=0
    right=len(nums)
    while left<right:
        mid=(right+left)/2
        if nums[mid] < target:
            left=mid+1 #target在右区间则找到了第一个不小于目标值的数,break
            #加1是为了如果left=right,就break,返回right;如果不加1就会是死循环
        else:
            right=mid #target在左区间则舍去右区间
    return right

第三类: 查找第一个大于目标值的数,可变形为查找最后一个不小于目标值的数
eg:在数组nums=[2,4,5,5,6]中查找数字5,就会返回数字6的位置4
    left=0
    right=len(nums)
    while left<right:
        mid=(right+left)/2
        if nums[mid] <= target: #唯一变的地方,加上等号
            left=mid+1 
        else:
            right=mid 
    return right

第四类:用子函数当作判断关系,并不是之前三类中简单的数字大小的比较
eg:这一题
思路:http://www.cnblogs.com/grandyang/p/8021421.html
所求的最大平均值一定是介于原数组的最大值和最小值之间,
所以目标是用二分法来快速的在这个范围内找到要求的最大平均值,
初始化left为原数组的最小值,right为原数组的最大值,然后mid就是left和right的中间值,
难点就在于如何得到mid和要求的最大平均值之间的大小关系,从而判断折半方向:
    如果我们已经算出来了这个最大平均值maxAvg,那么对于任意一个长度大于等于k的数组,
    如果让每个数字都减去maxAvg,那么得到的累加差值一定是小于等于0的。
    比如[1, 2, 3, 4]   k = 2,最大平均值maxAvg = 3.5,
    所以任何一个长度大于等于2的子数组每个数字都减去maxAvg的差值累加起来都小于等于0,
    只有产生这个最大平均值的子数组[3, 4],算出来才正好等于0,其他都是小于0的。
    那么我们可以根据这个特点来确定折半方向,让数组中的每一个数字都减去mid,然后算差值的累加和,
    一旦发现累加和大于0了,那么说明我们mid比maxAvg小,这样就可以判断方向了。

我们建立一个累加和数组sums,然后求出原数组中最小值赋给left,最大值赋给right,
题目中说了误差是1e-5,所以我们的循环条件就是right比left大1e-5,
然后我们算出来mid,定义一个minSum初始化为0,布尔型变量check,初始化为false。
然后开始遍历数组,先更新累加和数组sums,
注意这个累加和数组不是原始数字的累加,而是它们和mid相减的差值累加。
我们的目标是找长度大于等于k的子数组的平均值大于mid,
由于我们每个数组都减去了mid,那么就转换为找长度大于等于k的子数组的差累积值大于0。
我们建立差值累加数组的意义就在于通过sums[i] - sums[j]来快速算出j和i位置中间数字之和,
那么我们只要j和i中间正好差k个数字即可,然后minSum就是用来保存j位置之前的子数组差累积的最小值,
所以当i >= k时,我们用sums[i - k]来更新minSum,这里的i - k就是j的位置,
然后判断如果sums[i] - minSum > 0了,说明我们找到了一段长度大于等k的子数组平均值大于mid了,
就可以更新left为mid了,我们标记check为true,并退出循环。
在for循环外面,当check为true的时候,left更新为mid,否则right更新为mid,

#法2:二分法
class Solution:
    """
    @param: nums: an array with positive and negative numbers
    @param: k: an integer
    @return: the maximum average
    """
    def maxAverage(self, nums, k):
        if sum(nums)==0:
            return 0
        left=min(nums)
        right=max(nums)
        sums=[0 for x in range(0, len(nums)+1)] #长度为n+1的全0列表
            minSum=0
            mid=(right+left)/2 #目标是找长度大于等于k,且平均值大于mid的子数组
            check=False
            for i in range(1,len(nums)+1): #i=1,....,n
                sums[i]=sums[i-1]+nums[i-1]-mid #sums表示nums和mid相减的差值的累加和数组
        while right-left>1e-5:
                if i>=k:
                    minSum=min(minSum,sums[i-k]) #minSum就是用来保存j位置之前的子数组差累积的最小值
                if i>=k and sums[i]>minSum:  #说明找到了一段长度大于等k的子数组平均值大于mid了
                    check=True
                    break #注意break只能调出一层循环
            if check is True: #用break和if搭配跳出双层循环
                left=mid
            else:
                right=mid
        return left

##把上诉累加和数组sums变成单独的数字和sums和preSum
#    def maxAverage(self, nums, k):
#        left=min(nums)
#        right=max(nums)
#        while right-left>1e-5:
#            minSum=0
#            sums=0
#            preSum=0
#            mid=(right+left)/2
#            check=False
#            for i in range(len(nums)):
#                sums=sums+nums[i]-mid
#                if i>=k:
#                    preSum=preSum+nums[i-k]-mid
#                    minSum=min(minSum,preSum)
#                if i>=k-1 and sums>minSum:
#                    check=True
#                    break #注意break只能调出一层循环
#            if check is True: #用break和if搭配跳出双层循环
#                left=mid
#            else:
#                right=mid
#        return left


nums=[1,12,-5,-6,50,3]
k=3
print(Solution().maxAverage(nums,k))

#class Solution:
#    """
#    @param: nums: an array with positive and negative numbers
#    @param: k: an integer
#    @return: the maximum average
#    """
#    def maxAverage(self, nums, k):
#        """
#        :type nums: List[int]
#        :type k: int
#        :rtype: float
#        """
#        def getDelta(avg, nums, k):
#            accu = [0.0] * (len(nums) + 1)
#            minval_pos = None
#            delta = 0.0
#            for i in range(len(nums)):
#                accu[i+1] = nums[i] + accu[i] - avg
#                if i >= (k-1):
#                    if minval_pos == None or accu[i-k+1] < accu[minval_pos]:
#                        minval_pos = i-k+1
#                    if accu[i+1] - accu[minval_pos] >= 0:
#                        delta = max(delta, (accu[i+1] - accu[minval_pos]) / (i+1 - minval_pos))
#            return delta
#
#        left, delta = min(nums), float("inf")
#        while delta > 1e-5:
#            delta = getDelta(left, nums, k)
#            left += delta
#        return left
#
#nums=[1,12,-5,-6,50,3]
#k=3
#print(Solution().maxAverage(nums,k))

 

内容概要:本文围绕“光伏-储能-数据中心”系统的容量优化配置展开研究,旨在通过构建数学模型并结合Matlab编程实现,对园区内光伏发电、储能设备与数据中心算力负荷之间的多能互补关系进行协同优化。研究综合考虑可再生能源出力的波动性、储能系统的充放电特性以及数据中心的动态用电需求与算力调度特性,建立以最小化综合成本、降低碳排放强度、提升能源自给率等为目标的多目标优化模型,并采用先进的智能优化算法(如粒子群、灰狼、鲸鱼等)进行求解,从而确定光伏装机容量与储能系统配置的最优方案。文中提供了完整的Matlab代码实现流程,涵盖数据预处理、模型构建、算法求解与结果可视化全过程,属于综合能源系统与信息基础设施深度融合的前沿交叉课题。; 适合人群:具备电力系统、能源工程、自动化或计算机等相关专业背景,熟悉Matlab编程与基本优化算法原理,从事新能源利用、绿色数据中心、综合能源系统规划与低碳调度等方向的研究生、科研人员及工程技术人员。; 使用场景及目标:① 掌握光伏-储能-数据中心耦合系统的建模思路与多能流协同机制;② 学习基于Matlab的多目标容量优化配置方法与智能算法应用技巧;③ 为工业园区、数字经济园区及绿色数据中心的能源系统规划、节能减排与可持续运行提供科学决策依据和技术解决方案。; 阅读建议:建议结合所提供的Matlab代码,深入理解目标函数设计、约束条件设定及算法实现细节,可通过调整负荷参数、改变气候数据、引入新的优化目标或约束条件等方式进行拓展性实验,以深化对系统特性的认知并提升实际科研与工程应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值