[leetCode]38. 外观数列

在这里插入图片描述

解法一 递归+双指针

f ( 1 ) = 1 f(1) = 1 f(1)=1
f ( 2 ) = 1 1 f(2) = \bm11 f(2)=11
f ( 3 ) = 2 1 f(3) = \bm21 f(3)=21
f ( 4 ) = 1 2 1 1 f(4) = \bm12\bm11 f(4)=1211

通过观察可以知道要知道f(n)则需要知道f(n-1)…f(1),因此可以想到递归;通过观察可知,每个外观字符串都是由前一个字符串的每一个字符"计数值"(加粗字符)加上所计数的字符,因此可以使用双指针法对相同字符计数并完成字符串拼接。

class Solution {
    public String countAndSay(int n) {
        if(n == 1){
            return "1";
        }else{
            String preStr = countAndSay(--n);
            String ans = "";
            int len = preStr.length();
            int i = 0;//指针i指向preStr首字符(慢指针)
            for(int j = i+1; j < len; j++){//j为快指针用于跳过相同字符
                if(preStr.charAt(j)!=preStr.charAt(i)){//跳过相同字符结束
                    ans = ans + (j-i) + preStr.charAt(i);//j-i为跳过相同字符的数量, preStr.charAt(i)为所跳过的字符
                    i = j;//移动i指针
                }   
            }
            ans = ans + (len-i) + preStr.charAt(i);//上面遍历结束后可能还存在尾部连续字符,这一步就是拼接尾部字符
            return ans;
        }
    }
}

动态规化

因为递归并没有涉及到重复计算,所以动态规化时间复杂度也没有优化。

class Solution {
    public String countAndSay(int n) {
        String[] dp = new String[n];
        dp[0] = "1";
        for(int t = 1; t < n; t++){
            dp[t] = "";
            String preStr = dp[t-1];
            int len = preStr.length(); 
            int i = 0;
            for(int j = i + 1; j < len; j++){
                if(preStr.charAt(j)!=preStr.charAt(i)){
                    dp[t]=dp[t]+(j-i)+preStr.charAt(i);
                    i = j;
                }
            }
            dp[t]=dp[t]+(len-i)+preStr.charAt(i);
        }
        return dp[n-1];
    }
}

由于动态规化只记录了两个状态:前一个字符串和后一个字符串,因此可以用两个String 变量对空间复杂度进行优化:

class Solution {
    public String countAndSay(int n) {
        String preStr = "1";
        String curStr = "";
        for(int t = 1; t < n; t++){
            int len = preStr.length(); 
            int i = 0;
            for(int j = i + 1; j < len; j++){
                if(preStr.charAt(j)!=preStr.charAt(i)){
                    curStr= curStr + (j-i)+preStr.charAt(i);
                    i = j;
                }
            }
            curStr=curStr + (len-i)+preStr.charAt(i);
            preStr = curStr;
            curStr = "";
        }
        return preStr;
    }
}
posted @ 2020-06-24 10:11  消灭猕猴桃  阅读(58)  评论(0编辑  收藏  举报