Jerry's Blog

Recording what I learned everyday

View on GitHub


11 October 2019

LeetCode(34) -- 784, 788,

by Jerry Zhang

P784. Letter Case Permutation (Easy)

给一个字符串,我们可以把其中的字母换成任意大小写。列出所有的可能性。

答案

class Solution {
    public List<String> letterCasePermutation(String S) {
        List<StringBuilder> ans = new ArrayList();
        ans.add(new StringBuilder());

        for (char c: S.toCharArray()) {
            int n = ans.size();
            if (Character.isLetter(c)) {
                for (int i = 0; i < n; ++i) {
                    ans.add(new StringBuilder(ans.get(i)));
                    ans.get(i).append(Character.toLowerCase(c));
                    ans.get(n+i).append(Character.toUpperCase(c));
                }
            } else {
                for (int i = 0; i < n; ++i)
                    ans.get(i).append(c);
            }
        }

        List<String> finalans = new ArrayList();
        for (StringBuilder sb: ans)
            finalans.add(sb.toString());
        return finalans;
    }
}

21%

最优解

class Solution {
    public List<String> letterCasePermutation(String S) {
       List<String> answer = new ArrayList<String>();
        permutationHelper(answer, S.toCharArray() , 0);
        return answer;

    }

    public void permutationHelper(List<String> ans, char[] s , int index ){
        if( index == s.length){
            ans.add( new String(s));
            return;
        }
        if( Character.isAlphabetic(s[index])){
            s[index] = Character.toUpperCase(s[index]);
            permutationHelper(ans, s, index+1);
            s[index] = Character.toLowerCase(s[index]);
        }
        permutationHelper(ans, s , index+1);
    }
}

这个方法是最好的。

P788. Rotated Digits (Easy)

每个数字都旋转180度,如果能得到一个跟原来不一样的合法的数字,则该数有效。问从1到n一共有多少个这样的数字。

我的思路

每个数字都判断一下是否等于3,4,7或者2,5,6,9从而确定是否有效以及是否跟原来的数不一样了。

我的代码

public class E_788_RotatedDigits {
    public int rotatedDigits(int N) {
        int count = 0;
        for (int i = 1; i < N + 1; i++) {
            boolean valid = true;
            boolean different = false;
            int temp = i;
            while (temp != 0) {
                int r = temp % 10;
                if (r == 3 || r == 4 || r == 7) {
                    valid = false;
                    break;
                }
                if (r == 2 || r == 5 || r == 6 || r == 9) {
                    different = true;
                }
                temp /= 10;
            }
            if (valid && different) {
                count++;
            }
        }
        return count;
    }
}

48%

最优解

class Solution {
    public int rotatedDigits(int N) {
        char[] A = String.valueOf(N).toCharArray();
        int K = A.length;

        int[][][] memo = new int[K+1][2][2];
        memo[K][0][1] = memo[K][1][1] = 1;
        for (int i = K - 1; i >= 0; --i) {
            for (int eqf = 0; eqf <= 1; ++eqf)
                for (int invf = 0; invf <= 1; ++invf) {
                    int ans = 0;
                    for (char d = '0'; d <= (eqf == 1 ? A[i] : '9'); ++d) {
                        if (d == '3' || d == '4' || d == '7') continue;
                        boolean invo = (d == '2' || d == '5' || d == '6' || d == '9');
                        ans += memo[i+1][d == A[i] ? eqf : 0][invo ? 1 : invf];
                    }
                    memo[i][eqf][invf] = ans;
                }
        }

        return memo[0][1][0];
    }
}

肯定是为了保存算过的数据,可是弄K+1个2*2的矩阵,到底是怎么存数据的,实在是看不明白了。

P796. Rotate String (Easy)

把一个字符串最左边的字符挪到最右边,叫一次shift。如果字符串A经过若干次shift之后可以变成B,则返回true。

我的思路

一开始只想到暴力求解,可以用首字母是否相等来提高一点点效率。看答案最简单的方法是:把A重复一次,如果包含B,则返回true.

我的代码

class Solution {
    public boolean rotateString(String A, String B) {
        return A.length() == B.length() && (A + A).contains(B);
    }
}

答案

class Solution {
    public boolean rotateString(String A, String B) {
        if (A.equals(B)) return true;

        int MOD = 1_000_000_007;
        int P = 113;
        int Pinv = BigInteger.valueOf(P).modInverse(BigInteger.valueOf(MOD)).intValue();

        long hb = 0, power = 1;
        for (char x: B.toCharArray()) {
            hb = (hb + power * x) % MOD;
            power = power * P % MOD;
        }

        long ha = 0; power = 1;
        char[] ca = A.toCharArray();
        for (char x: ca) {
            ha = (ha + power * x) % MOD;
            power = power * P % MOD;
        }

        for (int i = 0; i < ca.length; ++i) {
            char x = ca[i];
            ha += power * x - x;
            ha %= MOD;
            ha *= Pinv;
            ha %= MOD;
            if (ha == hb && (A.substring(i+1) + A.substring(0, i+1)).equals(B))
                return true;

        }
        return false;
    }
}
tags: LeetCode