子数组的解释与专题

简介: 子数组的解释与专题

子数组:指在一个数组中,选择一些连续的元素组成的新数组。


例题一:6900. 统计完全子数组的数目


给你一个由 正 整数组成的数组 nums 。


如果数组中的某个子数组满足下述条件,则称之为 完全子数组 :


子数组中 不同 元素的数目等于整个数组不同元素的数目。

返回数组中 完全子数组 的数目。


子数组 是数组中的一个连续非空序列。


示例 1:


输入:nums = [1,3,1,2,2]

输出:4

解释:完全子数组有:[1,3,1,2]、[1,3,1,2,2]、[3,1,2] 和 [3,1,2,2] 。

示例 2:


输入:nums = [5,5,5,5]

输出:10

解释:数组仅由整数 5 组成,所以任意子数组都满足完全子数组的条件。子数组的总数为 10 。

提示:


1 <= nums.length <= 1000

1 <= nums[i] <= 2000

思路:1.用set以及unerdered_set容器暴力枚举


          2.滑动窗口


AC代码:


//暴力
class Solution {
public:
    int countCompleteSubarrays(vector<int>& nums) 
    {
        int sum=0;
        set<int> s;
        for(auto& x:nums)
        s.insert(x);
        int l=nums.size();
        for(int i=0;i<l;i++)
        {
            unordered_set<int> ss;
            for(int j=i;j<l;j++)
            {
                ss.insert(nums[j]);
                if(s.size()==ss.size())
                sum++;
            }
        }
        return sum;
    }
};


//滑动窗口
class Solution {
public:
    int countCompleteSubarrays(vector<int> &nums) {
        int m = unordered_set<int>(nums.begin(), nums.end()).size();
        unordered_map<int, int> cnt;
        int ans = 0, left = 0;
        for (int v: nums) { // 枚举子数组右端点 v=nums[i]
            cnt[v]++;
            while (cnt.size() == m) {
                int x = nums[left++];
                if (--cnt[x] == 0)
                    cnt.erase(x);
            }
            ans += left; // 子数组左端点 < left 的都是合法的
        }
        return ans;
    }
};

例题二:5057. 截断数组


给定一个长度为 n 的正整数数组a1,a2,…,an 和一个正整数 p。


现在,要将该数组从中间截断,得到两个非空子数组。


我们规定,一个数组的价值等于数组内所有元素之和模 p 的结果。


我们希望,将给定数组截断后,得到的两个非空子数组的价值之和尽可能大。


请你输出这两个非空子数组的价值之和的最大可能值。


输入格式


第一行包含两个整数 n 和 p。


第二行包含 n个整数 a1,a2,…,an。


输出格式


一个整数,表示价值之和的最大可能值。


数据范围


前 33 个测试点满足 2≤n≤10。

所有测试点满足 2≤n≤1e5,2≤p≤10000,1≤ai≤1e6。


输入样例1:


1. 4 10
2. 3 4 7 2


输出样例1:


16


输入样例2:


1. 10 12
2. 16 3 24 13 9 8 7 5 12 12


输出样例2:


13


思路:前缀和+枚举


AC代码:


#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5+10;
int a[N],n,p,sum[N],ans;
int sumn;
void solve()
{
    cin>>n>>p;
    for(int i=0;i<n;i++){
        cin>>a[i];
        sumn += a[i];
    }
    sum[0] = a[0];
    for(int i=1;i<n;i++){
        sum[i] = sum[i-1]+a[i];
    }
    if(n == 2){
        int cnt = a[0] % p + a[1] % p; 
        cout<<cnt<<endl;
        return ;
    }
    for(int i=1;i<n-1;i++){
        int tmp = sum[i-1]%p+(sumn-sum[i-1])%p;
        ans = max(ans,tmp);
    }
    cout<<ans<<endl;
    return ;
}
signed main()
{
  int t=1;
  while(t--)
  solve();
  return 0;
}

目录
相关文章
|
6月前
【题型总结】动态规划之按照某种形式分割数组以获得最值
【题型总结】动态规划之按照某种形式分割数组以获得最值
75 0
|
机器学习/深度学习 算法
代码随想录Day02 数组基础2 leetcode T977有序数组的平方, T209 长度最小的子数组,T59 螺旋矩阵II
代码随想录Day02 数组基础2 leetcode T977有序数组的平方, T209 长度最小的子数组,T59 螺旋矩阵II
56 0
|
6月前
|
存储 算法 程序员
【算法训练-数组 一】【数组子集】:最长无重复子数组
【算法训练-数组 一】【数组子集】:最长无重复子数组
42 0
|
C语言
【C语言刷题】调整奇数偶数顺序、有序序列合并以及有序序列判断
【C语言刷题】调整奇数偶数顺序、有序序列合并以及有序序列判断
62 0
图解LeetCode——209. 长度最小的子数组
图解LeetCode——209. 长度最小的子数组
66 1
图解LeetCode——209. 长度最小的子数组
|
C语言
C语言:输入两个升序排列的序列,将两个序列合并为一个有序序列并输出。
描述 输入两个升序排列的序列,将两个序列合并为一个有序序列并输出。 输入描述: 输入包含三行, 第一行包含两个正整数n, m,用空格分隔。n表示第二行第一个升序序列中数字的个数,m表示第三行第二个升序序列中数字的个数。 第二行包含n个整数,用空格分隔。 第三行包含m个整数,用空格分隔。
271 0
C语言:输入两个升序排列的序列,将两个序列合并为一个有序序列并输出。
|
算法 知识图谱 Python
Python|动态规划与回溯求数字个数
Python|动态规划与回溯求数字个数
84 0
|
存储 Java C++
力扣题目-两数相加(迭代递归,常用3种语言实现)
力扣题目-两数相加(迭代递归,常用3种语言实现)
115 0
LeetCode 1464. 数组中两元素的最大乘积
给你一个整数数组 nums,请你选择数组的两个不同下标 i 和 j,使 (nums[i]-1)*(nums[j]-1) 取得最大值。
71 0
复习C部分:1.for循环 2.do while循环语句 3.在一个有序数组中查找某个数,例如在1~10之间找7(例题包含计算n的阶乘+打印1~10的奇数+二分法)
复习C部分:1.for循环 2.do while循环语句 3.在一个有序数组中查找某个数,例如在1~10之间找7(例题包含计算n的阶乘+打印1~10的奇数+二分法)
116 0
复习C部分:1.for循环 2.do while循环语句 3.在一个有序数组中查找某个数,例如在1~10之间找7(例题包含计算n的阶乘+打印1~10的奇数+二分法)