1. 程式人生 > >C#LeetCode刷題之#788-旋轉數字(Rotated Digits)

C#LeetCode刷題之#788-旋轉數字(Rotated Digits)

問題

我們稱一個數 X 為好數, 如果它的每位數字逐個地被旋轉 180 度後,我們仍可以得到一個有效的,且和 X 不同的數。要求每位數字都要被旋轉。

如果一個數的每位數字被旋轉以後仍然還是一個數字, 則這個數是有效的。0, 1, 和 8 被旋轉後仍然是它們自己;2 和 5 可以互相旋轉成對方;6 和 9 同理,除了這些以外其他的數字旋轉以後都不再是有效的數字。

現在我們有一個正整數 N, 計算從 1 到 N 中有多少個數 X 是好數?

輸入: 10

輸出: 4

解釋: 在[1, 10]中有四個好數: 2, 5, 6, 9。注意 1 和 10 不是好數, 因為他們在旋轉之後不變。

注意:N 的取值範圍是 [1, 10000]。


X is a good number if after rotating each digit individually by 180 degrees, we get a valid number that is different from X.  Each digit must be rotated - we cannot choose to leave it alone.

A number is valid if each digit remains a digit after rotation. 0, 1, and 8 rotate to themselves; 2 and 5 rotate to each other; 6 and 9 rotate to each other, and the rest of the numbers do not rotate to any other number and become invalid.

Now given a positive number N, how many numbers X from 1 to N are good?

Input: 10

Output: 4

Explanation: There are four good numbers in the range [1, 10] : 2, 5, 6, 9.Note that 1 and 10 are not good numbers, since they remain unchanged after rotating.

Note:N  will be in range [1, 10000].


示例

public class Program {

    public static void Main(string[] args) {
        var N = 10;

        var res = RotatedDigits(N);
        Console.WriteLine(res);

        N = 68;

        res = RotatedDigits2(N);
        Console.WriteLine(res);

        Console.ReadKey();
    }

    private static int RotatedDigits(int N) {
        var res = 0;
        for(int i = 0; i < N; i++) {
            if(IsGoodDigit(i + 1)) res++;
        }
        return res;
    }

    private static bool IsGoodDigit(int n) {
        //先給出對映列表
        var dic = new Dictionary<char, char>() {
            {'0', '0'},
            {'1', '1'},
            {'2', '5'},
            {'5', '2'},
            {'6', '9'},
            {'8', '8'},
            {'9', '6'}
        };
        //建立 StringBuilder 加速字串運算
        var sb = new StringBuilder(n.ToString());
        //迴圈計算所有字串
        for(var i = 0; i < sb.Length; i++) {
            //不包含時,根據題意直接返回 false
            if(!dic.ContainsKey(sb[i])) return false;
            else {
                //進行“旋轉”
                sb[i] = dic[sb[i]];
            }
        }
        //跟原串不一樣時返回 true
        return n.ToString() != sb.ToString();
    }

    private static int RotatedDigits2(int N) {
        var res = 0;
        for(int i = 0; i < N; i++) {
            res += IsGoodDigit2(i + 1) ? 1 : 0;
        }
        return res;
    }

    private static bool IsGoodDigit2(int n) {
        //轉換成字串
        var bit = n.ToString();
        //包含3,4,7時,直接判定 false
        //因為旋轉後無效了
        if(bit.Contains('3') || bit.Contains('4') || bit.Contains('7'))
            return false;
        //包含2,5,6,9時,直接判定 true
        //因為旋轉後值肯定變了,並且程式碼執行到此處
        //說明原串中不包含3、4、7,不可能會無效
        if(bit.Contains('2') || bit.Contains('5') || bit.Contains('6') || bit.Contains('9')) {
            return true;
        }
        //其它所有情況直接判定 false 即可
        //包含 0,1,8 卻不能被上述程式碼命中
        //肯定不是好數
        return false;
    }

}

以上給出2種演算法實現,以下是這個案例的輸出結果:

4
28

分析:

顯而易見,以上2種演算法的時間複雜度均為: O(n) 。RotatedDigits2 使用了執行庫,所以不能認定它的時間複雜度為: O(1) 。