报数、压缩字符串

报数

报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:

  1. 1
    
  2. 11
    
  3. 21
    
  4. 1211
    
  5. 111221
    

1 被读作 “one 1” (“一个一”) , 即 11。
11 被读作 “two 1s” (“两个一”), 即 21。
21 被读作 “one 2”, “one 1” (“一个二” , “一个一”) , 即 1211。

给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。

注意:整数顺序将表示为一个字符串。

示例 1:

输入: 1
输出: “1”
示例 2:

输入: 4
输出: “1211”

class Solution {
   public String countAndSay(int n) {
       /*
       统计连续出现数字个数,和当前的数字组成新的字符串
       定义快慢指针i,j,和重复出现的字符个数
       如果i,j位置元素相等,则j++,cnt++
       否则,sb.append(cnt +""+ pre.charAt(i)),即记录到当前字符串中
       时间O(n),空间O(n)
       */

        ArrayList<String> strs = new ArrayList<>();
        strs.add(Integer.toString(1));

        for (int k = 1; k < n; k++){
            String pre = strs.get(k-1);
            StringBuffer sb = new StringBuffer();

            int i = 0, j = 0;
            int cnt = 0;
            while(j < pre.length()){
                if(pre.charAt(i) == pre.charAt(j)){
                    cnt++;
                    j++;
                }else{
                    sb.append(cnt +""+ pre.charAt(i));
                    i = j;
                    cnt = 0;
                }
            }
            if(cnt != 0){
                //有可能cnt不为0,说明当前还有字符没有加到sb中
                sb.append(cnt + "" +pre.charAt(i));
            }

            strs.add(sb.toString());
        }

        return strs.get(strs.size()-1);
    }

}

优化代码

class Solution {
 public String countAndSay(int n) {
        /*
        * 记录当前字符重复的数量
        * 注意这种找重复字符,并记录数量的方式
        * */
        ArrayList<String> strs = new ArrayList<>();
        strs.add(Integer.toString(1));
        
        for (int k = 1; k < n; k++){
            String pre = strs.get(k-1);
            StringBuffer sb = new StringBuffer();

            int i = 0, j = 0;
            while (j < pre.length()){
                if(j + 1 == pre.length() || pre.charAt(j) != pre.charAt(j+1)){
                    sb.append((j-i+1)+""+pre.charAt(i));
                    i = j + 1;
                }
                j++;
            }


            strs.add(sb.toString());
        }

        return strs.get(strs.size()-1);
    }
}

压缩字符串

给定一组字符,使用原地算法将其压缩。

压缩后的长度必须始终小于或等于原数组长度。

数组的每个元素应该是长度为1 的字符(不是 int 整数类型)。

在完成原地修改输入数组后,返回数组的新长度。

进阶:
你能否仅使用O(1) 空间解决问题?

示例 1:

输入:
[“a”,“a”,“b”,“b”,“c”,“c”,“c”]

输出:
返回6,输入数组的前6个字符应该是:[“a”,“2”,“b”,“2”,“c”,“3”]

说明:
"aa"被"a2"替代。"bb"被"b2"替代。"ccc"被"c3"替代。
示例 2:

输入:
[“a”]

输出:
返回1,输入数组的前1个字符应该是:[“a”]

说明:
没有任何字符串被替代。
示例 3:

输入:
[“a”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”]

输出:
返回4,输入数组的前4个字符应该是:[“a”,“b”,“1”,“2”]。

说明:
由于字符"a"不重复,所以不会被压缩。"bbbbbbbbbbbb"被“b12”替代。
注意每个数字在数组中都有它自己的位置。

class Solution {
        public int compress(char[] chars) {
            /*
            快慢指针法
            快慢指针i,j,相同字符数量cnt
            i和j位置值相同时,cnt++,j往后一部
            否则,将当前的cnt和字符按规则添加到sb中
            最后转换成字符数组即可
            时间O(n)空间O(n)
            */
        StringBuffer sb = new StringBuffer();

        int i = 0,j = 0, cnt = 0;
        int len = chars.length;

        while (j < len){
            if(chars[i] == chars[j]){
                cnt++;
                j++;
            }else {
                if (cnt > 1) {
                    sb.append(chars[i] + "" + cnt);
                } else if (cnt == 1) {
                    sb.append(chars[i]);
                }
                cnt = 0;
                i = j;
            }
        }

        if(cnt > 1){
            sb.append(chars[i] + "" + cnt);
        }else if(cnt == 1) {
            sb.append(chars[i]);
        }

        char []tmp = sb.toString().toCharArray();
        for (int k = 0; k < tmp.length; k++){
            chars[k] = tmp[k];
//            System.out.printf("%c ", chars[k]);
        }
        return tmp.length;
    }
}
class Solution {
        public int compress(char[] chars) {
        /*
        快慢指针i,j
        w为写入指针
        j遍历字符数组,相同的元素跳过,当前元素和后一个元素不相同时或者j就在最后一个元素时
        要将i位置的字符写入,并且当j>i时,在写入相同元素的个数
        i移动到j+1的位置
        时间O(n),空间O(1)
        */
        
        int i = 0, j = 0, w = 0;
            
        while(j < chars.length){
            
            if(j + 1 == chars.length || chars[j] != chars[j+1] ){
               chars[w++] = chars[i];
               
                if(j > i){
                    for(char c :(""+(j-i+1)).toCharArray()){
                    chars[w++] = c;
                    }
                }
                
                i = j + 1;
                
            }
            
            j++;
        }
            
            return w;
               
    }
}

上述两题操作类似。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值