Leetcode 最小調整數+滑動視窗遞增子序列

一隻老風鈴發表於2020-10-21

給定一個長度為N的陣列,以及一個乘積值B,每次只能對一個數增大或減少一個單位,問最少多少次使得陣列乘積為B

【思路】

要使得調整的次數最少,那麼最開始調整的那個數字,應該是最小的數。

貪心策略:選最小的數調整,其它部分數乘積最大(自己需要調整的偏移值就儘可能小)

 

先對原先陣列從小到大排序。

對於k  如果 B%k==0  =》  B=B/k   即如果能整除,那麼直接整除

如果B%k!=0  =》 不能整除 那麼 a[k]--  (即調整一次  因為最差情況下a[k] 調整為1 那麼一定能整除)

直到k=>N

int fun(vector<int> arr,int b)
{
    
    int count=0;
    for(int i=0;i<arr.size();i++)
    {
        if(b%arr[i]==0) 
        {
            b/=arr[i];
        }
        else
        {
            arr[i]--;
            count++;
            i--;
        }
    }
    
    
}

 

 

【特殊連續遞增序列】

 

給定一個序列,求這樣的一個完美序列,是一個連續的子序列,並且序列中每一個數都大於等於前面所有數字之和。 

基本思路:

滑動視窗,left=1 right=1 維護一個sum變數表示視窗中前面k-1個的和:

  • 若當前視窗滿足 arr[right]>=sum 那麼 更新res     sum+=arr[right]  同時right++ 
  • 若當前視窗不滿足  視窗左邊縮減             同時    sum-=arr[left]      那麼left++

易錯點:

原本思路是 add[k]存放前面k個數字之和,那麼求解區間直接相減: add[right]-add[left-1]  =》  add會加法溢位

#include<iostream>
#include<vector>
using namespace std;
int main()
{
    int n;
    cin>>n;
    int k;
    for(int i=0;i<n;i++)
    {
        cin>>k;
        vector<long long> arr(k+1,0);
        arr[0]=0;
        //完成初始化
        for(int j=1;j<=k;j++)
            cin>>arr[j];
        int left=1;
        int right=1;
        long long sum=0;  //滑動視窗內之和
        int ans=0;
        while(right<=k)
        {
            if(arr[right]>=sum)  //滿足
            {
                ans=max(ans,right-left+1);  //記錄下符合要求視窗的長度
                sum+=arr[right];
                right++;  //,滿足連續遞增
            }
            else
            {
                sum-=arr[left];
                left++;
            }
        }
        cout<<ans<<endl;
    
    }
}

 

 

 

相關文章