1. 程式人生 > 實用技巧 >Leetcode 38 外觀數列

Leetcode 38 外觀數列

  一個變種的斐波那契數列,DP 沒跑了,問題在於如何處理外觀的邏輯。用棧儲存當前計數的元素,遞迴表示:

 public final String countAndSay0(int n) {
        String[] cache = new String[n + 1];
        return countAndSay0(n, cache);
    }

    public final String countAndSay0(int n, String[] cache) {
        if (n == 1) {
            return "1";
        }
        
if (n == 2) { return "11"; } if (cache[n] != null) { return cache[n]; } String pre = countAndSay0(n - 1, cache); StringBuilder sb = new StringBuilder(); Stack<Character> stack = new Stack<Character>(); for (int
i = 0; i < pre.length(); i++) { //末尾元素處理 if (i == pre.length() - 1) { if (stack.size() == 0) { sb.append("1" + pre.charAt(pre.length() - 1)); } else if (pre.charAt(i) == stack.get(0)) { sb.append(String.valueOf(stack.size()
+ 1)).append(String.valueOf(stack.get(0))); } else { sb.append(String.valueOf(stack.size())).append(String.valueOf(stack.get(0))); sb.append("1" + pre.charAt(pre.length() - 1)); } break; } //普通元素處理 if (stack.size() > 0 && pre.charAt(i) != stack.get(0)) { sb.append(String.valueOf(stack.size())).append(String.valueOf(stack.get(0))); stack.clear(); stack.push(pre.charAt(i)); continue; } stack.push(pre.charAt(i)); } stack = null; //記錄快取 cache[n] = sb.toString(); return cache[n]; }

  遞推表示:

public final String countAndSay1(int n) {
        if (n == 1) {
            return "1";
        }
        String[] cache = new String[n + 1];
        cache[1] = "1";
        cache[2] = "11";
        Stack<Character> stack = new Stack<Character>();
        for (int i = 3; i <= n; i++) {
            String pre = cache[i - 1];
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < pre.length(); j++) {
                //末尾元素處理
                if (j == pre.length() - 1) {
                    if (stack.size() == 0) {
                        sb.append("1").append(pre.charAt(pre.length() - 1));
                    } else if (pre.charAt(j) == stack.get(0)) {
                        sb.append(String.valueOf(stack.size() + 1)).append(String.valueOf(stack.get(0)));
                    } else {
                        sb.append(String.valueOf(stack.size())).append(String.valueOf(stack.get(0))).append("1").append(pre.charAt(pre.length() - 1));
                    }
                    stack.clear();
                    break;
                }
                //普通元素處理
                if (stack.size() > 0 && pre.charAt(j) != stack.get(0)) {
                    sb.append(String.valueOf(stack.size())).append(String.valueOf(stack.get(0)));
                    stack.clear();
                    stack.push(pre.charAt(j));
                    continue;
                }
                stack.push(pre.charAt(j));
            }
            cache[i] = sb.toString();
        }
        return cache[n];
    }

  用兩個區域性變數,一個儲存計數元素,一個儲存當前元素個數來代替棧:

public final String countAndSay(int n) {
        if (n == 1) {
            return "1";
        }
        if (n == 2) {
            return "11";
        }
        StringBuilder pre = new StringBuilder("11");
        for (int i = 3; i <= n; i++) {
            StringBuilder sb = new StringBuilder();
            char currentChar = pre.charAt(0);
            int currentNum = 1;
            for (int j = 1; j < pre.length() + 1; j++) {
                if (j == pre.length()) {
                    sb.append(currentNum).append(currentChar);
                    break;
                }
                if (pre.charAt(j) == currentChar) {
                    currentNum++;
                    continue;
                }
                sb.append(currentNum).append(currentChar);
                currentNum = 1;
                currentChar = pre.charAt(j);
            }
            pre = sb;
        }
        return pre.toString();
    }