LeetCode 357. 計算各個位數不同的數字個數

解題思路

非常經典的數位dp。麻煩的地方在於要處理前導0.例如010這樣的數據如果不處理前導0的話,會認爲有兩個0.
數位dp的思路這裏不再闡述。
dp[pos][sta]表示前pos位,狀態爲sta滿足題意的數的個數。
注意使用位運算來查看有沒有重複的數。

代碼

class Solution {
public:
    long long dp[30][1<<11];
    int bit[30];
    bool check(int sta,int i)
    {
        return sta&(1<<(i));
    }
    long long dfs(int pos,int sta,bool limit,bool zero)
    {
        if(pos==-1) return 1;
        if(limit==0&&zero==0&&dp[pos][sta]!=-1) return dp[pos][sta];
        int up=limit?bit[pos]:9;
        long long ans=0;
        for(int i=0;i<=up;i++)
        {
            if(zero&&i==0)
            {
                ans+=dfs(pos-1,sta,limit&&i==up,zero&&i==0);
            }
            else
            {
                if(check(sta,i))
                {
                    continue;
                    //cout<<sta<<" "<<i<<endl;
                    //ans+=dfs(pos-1,sta|(1<<i),sta&&0,limit&&i==up,zero&&i==0);
                }
                else
                {
                    ans+=dfs(pos-1,sta|(1<<(i)),limit&&i==up,zero&&i==0);
                }
            }
        }
        if(limit==0&&zero==0) dp[pos][sta]=ans;
        return ans;
    }
    long long solve(long long x)
    {
        int k=0;
        while(x)
        {
            bit[k++]=x%10;
            x/=10;
        }
        return dfs(k-1,0,1,1);
    }
    int countNumbersWithUniqueDigits(int n) {
        long long x=1;
        memset(dp,-1,sizeof(dp));
        while(n)
        {
            x*=10;
            n--;
        }
        return solve(x-1);
    }
};
發佈了408 篇原創文章 · 獲贊 166 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章