力扣-1630. 等差子数组

1.题目介绍

题目地址(1630. 等差子数组 - 力扣(LeetCode))

https://leetcode.cn/problems/arithmetic-subarrays/

题目描述

如果一个数列由至少两个元素组成,且每两个连续元素之间的差值都相同,那么这个序列就是 等差数列 。更正式地,数列 s 是等差数列,只需要满足:对于每个有效的 is[i+1] - s[i] == s[1] - s[0] 都成立。

例如,下面这些都是 等差数列

1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9

下面的数列 不是等差数列

1, 1, 2, 5, 7

给你一个由 n 个整数组成的数组 nums,和两个由 m 个整数组成的数组 lr,后两个数组表示 m 组范围查询,其中第 i 个查询对应范围 [l[i], r[i]] 。所有数组的下标都是 从 0 开始 的。

返回 boolean 元素构成的答案列表 answer 。如果子数组 nums[l[i]], nums[l[i]+1], ... , nums[r[i]] 可以 重新排列 形成 等差数列answer[i] 的值就是 true;否则answer[i] 的值就是 false

 

示例 1:

[4,6,5,9,3,7]
[0,0,2]
[2,3,5]
[true,false,true]
[5,9,3,7] 。
[3,5,7,9] 。

示例 2:

输入:nums = [-12,-9,-3,-12,-6,15,20,-25,-20,-15,-10], l = [0,1,6,4,8,7], r = [4,4,9,7,9,10]
输出:[false,true,false,false,true,true]

 

提示:

  • n == nums.length
  • m == l.length
  • m == r.length
  • 2 <= n <= 500
  • 1 <= m <= 500
  • 0 <= l[i] < r[i] < n
  • -105 <= nums[i] <= 105

2.题解

2.1暴力枚举

思路

很简单,将数组根据l和r的要求进行拆分排序,然后从头到尾进行遍历,判断是否为等差数组

代码

  • 语言支持:C++

C++ Code:

class Solution {
public:
    vector<bool> checkArithmeticSubarrays(vector<int>& nums, vector<int>& l,vector<int>& r) {
        int m = l.size();
        vector<bool> ans;
        for (int i = 0; i < m; i++) {
            vector<int> subNums(nums.begin() + l[i], nums.begin() + r[i] + 1);
            sort(subNums.begin(), subNums.end());
            int n = subNums.size();
            bool flag = true;
            if (n == 2) {
                ans.push_back(flag);
                continue;
            }
            int sub = subNums[1] - subNums[0];
            for (int j = 2; j < n; j++) {
                if (subNums[j] - subNums[j - 1] != sub) {
                    flag = false;
                    break;
                }
            }
            ans.push_back(flag);
        }
        return ans;
    }
};

复杂度分析

  • 时间复杂度:每个子数组的排序操作为‘o(k log k)’,其中‘k 是子数组的长度。
    由于总共有“m个查询,所以总时间复杂度为”o(m*k log k)”,最坏情况下为O(mnlogn)
  • 空间复杂度:需要额外的空间来存储每个子数组,最坏情况下总空间复杂度为O(n)

这个解决方案对于给定的限制是高效的,因为 n 和 m 都是 500 以内,排序操作在这个范围内是可以接受的。

2.2 优化(判断等差数列——去除排序步骤)

思路

对于每一个子数组,我们考虑不进行排序判断其是否为等差数列
第一次遍历,确定其最大值,最小值;通过这两个值我们可以判断该数组如果为等差,那么他的公差为

代码

class Solution {
public:
    vector<bool> checkArithmeticSubarrays(vector<int>& nums, vector<int>& l,vector<int>& r) {
        int m = l.size();
        vector<bool> ans;
        for (int i = 0; i < m; i++) {
            int start = l[i], end = r[i];
            int n = end - start + 1; // 子数组总个数 
            int max_value = INT_MIN, min_value = INT_MAX;
            bool isArithmetic = true;
            // 子数组长度为2则必为等差数列
            if(n == 2){
                ans.push_back(isArithmetic);
                continue;
            }
            // 遍历子数组,获得最大值,最小值
            for(int j = start; j <= end; j++){
                max_value = max(max_value, nums[j]);
                min_value = min(min_value, nums[j]);
            }

            // 判断子数组是否为等差数列
            if((max_value - min_value) % (n - 1) != 0){
                isArithmetic = false;
                ans.push_back(isArithmetic);
                continue;
            }
            // 计算公差
            int diff = (max_value - min_value) / (n - 1);
            if(diff == 0){
                ans.push_back(isArithmetic);
                continue;
            }
            vector<bool> visitor(n, false); // 判断是否遇到过该数
            // 遍历数组
            for(int j = start; j <= end; j++){
                if((nums[j] - min_value) % diff != 0){
                    isArithmetic = false;
                    break;
                }
                int pos = (nums[j] - min_value) / diff;
                if(pos >= n || visitor[pos]){
                    isArithmetic = false;
                    break;
                }
                visitor[pos] = true;
            }
            ans.push_back(isArithmetic);
        }
        return ans;
    }
};

复杂度分析

  • 时间复杂度:
    每次查询中,我们需要遍历子数组找最小值和最大值,这需要o(k)”时间。·然后我们需要再次遍历子数组来判断每个数字的位置,最坏情况下总共需要o(k)
    所以每个查询的时间复杂度是“o(k)”。
    总共有“m个查询,所以总时间复杂度为’o(m*k)’最坏情况下为o(nm)
  • 空间复杂度:
    主要是用于记录每个数字位置的布尔数组‘seen’,其大小为子数组的长度,最坏情况下为“o(n)”。总的空间复杂度为 'o(n) 。
posted @   DawnTraveler  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示