【LeetCodeウィークリーコンペソリューション】第340回ウィークリーコンペソリューション - 2つのポイント、BFSの最適化

【トピック一覧】

対角線上の素数等価距離

最小化された数値のペア間の最大差
ネットワーク グラフ内の最小訪問グリッド番号


対角線上の素数

  対角線上の数値をたどって、最大の素数を維持します。

class Solution {
    
    
public:
    bool isprime(int n){
    
    
        if(n==1)return false;
        if(n==2)return true;
        for(int i=2;i<=sqrt(n);i++){
    
    
            if(n%i==0)return false;
        }
        return true;
    }
    int diagonalPrime(vector<vector<int>>& nums) {
    
    
        int res=0;
        for(int i=0;i<nums.size();i++){
    
    
            if(isprime(nums[i][i])){
    
    
                res=max(res,nums[i][i]);
            }
            if(isprime(nums[i][nums.size() - i - 1])){
    
    
                res=max(res,nums[i][nums.size() - i - 1]);
            }
        }
        return res;
    }
};

等価距離と

  現在の数値がnums[i] = 7 であると仮定します。 nums[i]=7数値[ i ] _ _ _=7、現在の7 77の左に 7 が付いている77の距離の合計はdis [ i ] dis[i]d i s [ i ] 、 ans ans がプレフィックス配列に存在します7 7 _ _7とその前の7 77の位置はidx idxですi d x 、その後プレフィックス 7 の77対現在の7 77の寄与値はdis [ idx ] + ans ∗ ( i − idx ) dis[idx]+ans*(i-idx) です。d[ i d x ] _+s _(私はi d x )
これはプレフィックスのみを計算するため、後ろから前に再度実行し、各位置でのプレフィックスの寄与とサフィックスの寄与の合計が最終的な答えになります。

class Solution {
    
    
public:
    vector<long long> distance(vector<int>& nums) {
    
    
        int n=nums.size();
        vector<long long> res(n,0);
        vector<long long> cnt(n,0);
        map<int,int> idx;
        map<int,int> ans;
        for(auto num:nums)idx[num]=-1,ans[num]=0;
        for(int i=0;i<n;i++){
    
    
        //其实这里可以不用绝对值函数,比赛时间紧懒得改了
            if(idx[nums[i]]!=-1) res[i]=res[idx[nums[i]]]+ans[nums[i]]*abs(i-idx[nums[i]]);
            idx[nums[i]]=i;
            ans[nums[i]]++;
        }
        for(auto num:res)cout<<num<<" ";
        for(auto num:nums)idx[num]=-1,ans[num]=0;
        for(int i=n-1;i>=0;i--){
    
    
            if(idx[nums[i]]!=-1) cnt[i]=cnt[idx[nums[i]]]+ans[nums[i]]*abs(i-idx[nums[i]]);
            idx[nums[i]]=i;
            ans[nums[i]]++;
            res[i]+=cnt[i];
        }
        cout<<endl;
        for(auto num:res)cout<<num<<" ";
        return res;
    }
};

ペアの最大差を最小化する

  まず、元の配列で列挙することは不可能であるため、ソートは確実であり、ソートにより最小の差を計算することが容易になります。次に、次のような機能があります。最適解の各対数ペアは隣接している必要があります選択した数字のペアが左右の数字と等しくない数字で区切られている場合、中央の数字と間隔の外側の数字がペアを形成し、間隔の繰り返しが発生することが反証できます。[ 1 , 2 , 2 , 2 , 4 ] [1,2,2,2,4]のように同じ数字が連続する場合[ 1 2 2 2 [4 ] を参照すると、隣接しない選択方法もありますが、最終結果は隣接する方法と等しく、最適な数値ペアは依然として隣接していることがわかります。しかし、ここで問題があり、先頭と末尾の番号は、それぞれの番号を選択して、左右の番号とチームを組むことができるため、現在の組み合わせが最適であるとは言い切れません。フォローアップの解決策。
  最大値と最小値を見たときに、まず最小値と最大値を見たときに 2 つの点を考えるべきだという人もいます。この問題は逆変換しかできないため、数値の差の最大値はXXX、バイナリ メソッドを使用して可能性のあるXXX を計算し、この数値がppに等しい場合、差がこの値より小さいペアの数を数えます。p、次にXXX は条件を満たす結果です。

class Solution {
    
    
public:
    int minimizeMax(vector<int>& nums, int p) {
    
    
        if(p==0) return 0;
        int n=nums.size();
        sort(nums.begin(),nums.end());
        // for(auto num:nums)cout<<num<<" ";
        // cout<<endl;
        auto check=[&](int limit){
    
    
            int ans=0;
            for(int i=1;i<n;i++) if(nums[i]-nums[i-1]<=limit) ans++,i++;
            return ans>=p;
        };

        int l=0,r=(nums[n-1]-nums[0]);
        while(l<r){
    
    
            int mid=(l+r)/2;
            if(check(mid)) r=mid;//数量大于p说明当前X太大了
            else l=mid+1;
        }
        return l;
    }
};

ネットワーク グラフ内で訪問したセルの最小数

私はこれまで暗記型 BFS をやったことがありませんでしたが、非常に斬新だと思います。BFS を使用すると、毎回多くの感動的な問題を解くことができます。後で考えてみましょう。実際、すべてのステップを歩くために最善を尽くし、その後、ステップ サイズが徐々に増加するため、最小のステップ サイズで各グリッドに初めてアクセスすることが保証されます。すごい。

class Solution {
    
    
public:
    int minimumVisitedCells(vector<vector<int>>& grid) {
    
    
        int m=grid.size(),n=grid[0].size();
        vector<vector<bool>> vis(m,vector<bool> (n,false));
        queue<pair<int,int>> q;
        q.push({
    
    0,0});
        vis[0][0]=true;
        int res=0;

        while(!q.empty()){
    
    
            res++;
            int ans=q.size();
            for(int i=0;i<ans;i++){
    
    
                auto [r,c]=q.front();
                q.pop();
                if(r==m-1&&c==n-1) return res;
                int k=grid[r][c];
                if(k==0)continue;//寸步难行
                if(r+k>=m-1&&c==n-1) return res+1;//下一步就能走到终点
                if(r==m-1&&c+k>=n-1) return res+1;
                for(int j=c+1;j<n&&j<=k+c;j++){
    
    //向右走
                    if(!vis[r][j]){
    
    
                        q.push({
    
    r,j});
                        vis[r][j]=true;
                    }
                }
                for(int j=r+1;j<m&&j<=r+k;j++){
    
    //向下走
                    if(!vis[j][c]){
    
    
                        q.push({
    
    j,c});
                        vis[j][c]=true;
                    }
                }
            }
        }
        return -1;
    }
};

Guess you like

Origin blog.csdn.net/qq_44623371/article/details/130040384