zoukankan      html  css  js  c++  java
  • 左神算法进阶班8_1数组中累加和小于等于aim的最长子数组

    【题目】

    给定一个数组arr,全是正数;一个整数aim,求累加和小于等于aim的,最长子数组,要求额外空间复杂度O(1),时间复杂度O(N)

    【题解】

    使用窗口:

    双指针,当sum <= aim,,R->, 当sum > aim, L->记录最大的R - L即可

    【进阶】

    给定一个数组arr,值可正,可负,可0;一个整数aim,求累加和小于等于aim的,最长子数组,要求时间复杂度O(N)

    【题解】

    之所以比原题更难,是因为负数可以使得整个子数组开始的和很大,但加到负数时,整体和就变小了

    借助两个数组

    min_sum[] //min_sum[i] == 即必须以i开头的数组的最小累积和

    min_sum_index[]// min_sum_index[i] == 即以i开头数组的最小累加和的达到的最右端位置

    技巧:

    从数组的后向前算:

    当n位置的最小累加和为负数时,那么n - 1的最小累加和一定是自己加上n的最小累加和,其最右边界与n相同

    当n位置的最小累加和为正数时,那么n - 1的最小累加和一定是自己,因为再向后面加也是加一个正数,其最右边界就是自己的位置

    求解:

    从第0个数开始,R直接到0位置的最右边界,sum + 0位置的最小累加和,若,sum<aim, 则再加入R位置的最小累加和,并且R移到R位置的最右边界
    直至sum>aim,则可以知道最长数组是多少了

    【代码】

     1 #pragma once
     2 #include <iostream>
     3 #include <vector>
     4 
     5 using namespace std;
     6 
     7 int theLongestArray(vector<int>v, int aim)
     8 {
     9     //使用两个指针,作为窗口的左右端
    10     int l = -1;
    11     int r = 0;
    12     int sum = 0;
    13     int res = 0;
    14     for (; r < v.size(); ++r)
    15     {
    16         sum += v[r];
    17         while (sum > aim && l < r)//向右移动窗口
    18         {
    19             ++l;
    20             sum -= v[l];
    21         }
    22         res = res > (r - l) ? res : (r - l);
    23     }
    24     return res;
    25 }
    26 
    27 
    28 int theLongestArray_2(vector<int>v, int aim)
    29 {
    30     int* min_sum = new int[v.size()];//以i开头的数组的最小和
    31     int* min_sum_index = new int[v.size()];//以i开头的数组的最小和数组右端
    32     for (int i = v.size()-1; i >= 0; --i)
    33     {
    34         if (i + 1 < v.size() && min_sum[i + 1] < 0)//右端最小和为负数,则可加上自己比自己更小
    35         {
    36             min_sum[i] = min_sum[i + 1] + v[i];
    37             min_sum_index[i] = min_sum_index[i + 1];
    38         }
    39         else//右端为整数,加上自己比自己大,那么就以自己为最小的数组和
    40         {
    41             min_sum[i] = v[i];
    42             min_sum_index[i] = i;
    43         }
    44     }
    45     //定义窗口的左右边界
    46     int l = -1;
    47     int r = 0;
    48     int res = 0;
    49     int sum = 0;
    50     for (int i=0;i<v.size();++i)
    51     {
    52         sum += min_sum[i];
    53         r = min_sum_index[i];
    54         while (l<r && sum>aim)
    55         {
    56             ++l;
    57             sum -= v[l];
    58         }
    59         res = res > (r - l) ? res : (r - l);
    60     }
    61     delete[]min_sum;
    62     delete[]min_sum_index;
    63     return res;
    64 
    65 }
    66 void  Test()
    67 {
    68     vector<int>v;
    69     v = {1,2,3,4,5,1,1,1,1,1,1,1,7,8,9};
    70     cout << theLongestArray(v, 7) << endl;
    71     v = { 1,2,3,4,5,1,1,-99,1,1,1,1,1,7,8,9,10,11,-99};
    72     cout << theLongestArray_2(v, 7) << endl;
    73 }
  • 相关阅读:
    Tomcat常设参数
    JSON
    Linux常用命令
    【Swagger2】【3】API注解详解,以及注解常用参数配置
    【实战问题】【13】报错springBoot-tk.mybatis.mapper.MapperException: 无法获取实体类com.xx.User对应的表名!
    【实战问题】【12】报错org.apache.commons.lang.exception.NestableRuntimeException
    【Java】【50】BeanUtils.copyProperties();只从源对象中拷贝自己为null的值
    【JS】【32】清空file文件域
    【MySQL】【7】AES_ENCRYPT()加密与AES_DECRYPT()解密
    【Swagger2】【2】SpringBoot整合Swagger2
  • 原文地址:https://www.cnblogs.com/zzw1024/p/11097757.html
Copyright © 2011-2022 走看看