找到所有好下标&&公因子的数目

63 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

[6190. 找到所有好下标]

leetcode.cn/problems/fi…

image-20220925145712888


前后缀分解模型

先进行预处理操作:

f(i) : 表示以i为终点的,单调递减的序列的最大长度

  • 如果a[i-1] < a[i] :当前f(i) = 1 即:自己本身的长度
  • 如果a[i-1] >= a[i] 当前f(i) = f(i-1)+1 即:以i-1为终点的单调递减的序列的最大长度 +自己本身

g(i):表示以i为起点的,单调递增的序列的最大长度

  • 如果a[i+1] < a[i] :当前f(i) = 1 即:自己本身的长度
  • 如果a[i+1] >= a[i] 当前g(i) = g(i+1)+1 即:以i+1为起点的,单调递增的序列的最大长度 +自己本身

当我们想判断第i个位置是否满足要求:

要判断第i个位置前k个元素是不是单调递减的,也就是判断f(i-1)是否>=k

要判断第i个位置后k个元素是不是单调递增的,也就是判断g(i+1)是否>=k

if(f[i-1] >= k && g[i+1]>=k) {//当前i是好下下标}


class Solution {
public:
    vector<int> goodIndices(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> f(n);//表示以i为终点的,单调递减的序列的最大长度
        vector<int> g(n);//表示以i为起点的,单调递增的序列的最大长度
​
        //从前往后推f数组
        for(int i = 0;i<n;i++)
        {
            f[i] = 1;
            if(i!=0 && nums[i-1] >= nums[i])
            {
                f[i] = f[i-1]+1;
            }
        }
        //从后往前推g数组
        for(int i = n-1;i>=0;i--)
        {
            g[i] = 1;
            if(i+1<n &&nums[i+1] >= nums[i])
            {
                g[i] = g[i+1]+1;
            }
        }
​
        vector<int> ans;
        //找 k <= i <n-k之间的好下标
        for(int i = k;i<n-k;i++)
        {
            //i之前的k个元素是非递增的 :f[i-1]>=k
            //i之后的k个元素是非递减的 :g[i+1]>=k
            if(f[i-1]>=k && g[i+1]>=k)
                ans.push_back(i);//当前i是好下标
        }
        return ans;
    }
};

[6192. 公因子的数目]

leetcode.cn/problems/nu…

image-20221002152316457


做法:枚举1~min(a,b)的数检查即可,找出能同时被a和b整除的数

当然因为a和b的范围都在1000以内,所以也可以直接枚举1~1000,判断能不能同时被a和b整除

class Solution {
public:
    int commonFactors(int a, int b) {
        int count = 0;
        for(int i = 1;i<=min(a,b);i++)
        {
            if(a%i == 0 && b%i == 0)
                count++;
        }
        return count;
    }
};

时间复杂度:O(min(a,b))