华为笔试题 之 简易压缩算法

一、题目

有一种简易压缩算法:针对由全部小写字母组成的字符串,将其中连续超过两个相同字目的部分压缩成连续个数加该字母,其他部分保持原样不变。

例如,字符串:aaabccccd 经过压缩成为字符串:3ab4cd。请您编写一个unZip函数,根据输入的字符串,判断其是否为合法压缩过的字符串。
若输入合法,则输出解压后的字符串,否则输出:!error 来报告错误。

测试:3ab4cd合法,aa4b合法,caa4b合法,3aa4b不合法,22aa不合法,2a4b不合法,22a合法

二、代码

package com.huawei.nowcoder;

import com.sun.istack.internal.NotNull;
import java.util.Scanner;

public class MyTest2 {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        String in = sc.nextLine();
        if (null == in || in.trim().equals("")) {
            return;
        }

        System.out.println(unZip(in.toCharArray()));
    }

    /**
     * 解压
     * @param input
     * @return
     */
    private static String unZip(char[] input) {
        if (!checkInput(input, null)) {
            System.out.println("!error");
            return "";
        }

        StringBuilder strUnZip = new StringBuilder();
        int i = 0, len = input.length;

        while (i < len) {
            char c = input[i];
            if (Character.isDigit(c)) {
                StringBuilder countSb = new StringBuilder();
                countSb.append(c);

                char nextC = c;
                int nextI = i + 1;
                if (nextI < len && Character.isDigit(input[nextI])) {
                    // 输入字符串长度大于1,截取剩余部分递归用
                    char[] remain = new char[len - nextI];
                    System.arraycopy(input, nextI, remain, 0, (len - nextI));
                    // 下一个也为数字时,要和当前数字组合成一个整数
                    nextC = findCount(remain, countSb);
                } else if (nextI < len) {
                    nextC = input[nextI];
                }

                int count = Integer.parseInt(countSb.toString());
                for (int s = 0; s < count; s++) {
                    strUnZip.append(nextC);
                }
                i = nextI + countSb.length();
            } else {
                strUnZip.append(c);
                i ++;
            }
        }
        return strUnZip.toString();
    }

    /**
     * 获取字母前的数字,比如:123a,获取到123,返回a
     * @param input
     * @param countSb
     * @return
     */
    private static char findCount(char[] input, StringBuilder countSb) {
        // 如果剩最后一个,肯定是小写字母
        int len = input.length;
        char c = input[0];
        if (len == 1) {
            return c;
        }

        countSb.append(c);
        char nextC = input[1];
        if (Character.isDigit(nextC)) {
            char[] remain = new char[len - 1];
            System.arraycopy(input, 1, remain, 0, len - 1);
            return findCount(remain, countSb);
        } else {
            return nextC;
        }
    }

    /**
     * 校验合法性,非法返回false
     * @param input
     * @param lastChar
     * @return
     */
    private static boolean checkInput(@NotNull char[] input, Character lastChar) {
        if (null == input || input.length == 0) {
            return false;
        }

        int len = input.length;
        char c = input[0];

        // 只有一个字符且为小写字母
        if (len == 1 && Character.isLowerCase(c)) {
            return true;
        }

        // 输入字符串长度大于1,截取剩余部分递归用
        char[] remain = new char[len - 1];
        System.arraycopy(input, 1, remain, 0, len - 1);

        char nextC = input[1];
        boolean flag = false;
        // 3ab4cd合法,aa4b合法,caa4b合法,3aa4b不合法,22aa不合法,2a4b不合法,22a合法
        if (Character.isDigit(c)) {

            if (Character.isLowerCase(nextC)) {
                if (null == lastChar && Integer.parseInt(String.valueOf(c)) > 2) {
                    // 下一个字符如果是小写字母,则该数字要大于2
                    flag = true; // 第一个
                } else if (lastChar != null && Character.isDigit(lastChar)) {
                    // c是数字,c前面字符也是数字时,合法
                    flag = true;
                } else if (lastChar != null && Character.isLowerCase(lastChar)) {
                    if (Character.isLowerCase(nextC) && Integer.parseInt(String.valueOf(c)) > 2) {
                        // c前面是小写字母,如果c后面是字母,则c必须大于2
                        flag = true;
                    } else if (Character.isDigit(nextC)) {
                        // 如果c后面是数字时合法
                        flag = true;
                    }
                }
            } else if (Character.isDigit(nextC)) {
                flag = true;
            }

        } else if (Character.isLowerCase(c)) {
            // 为小写字母时,后面跟着的相同字母不能超过2个
            if (null == lastChar) {
                flag = true; // 第一个
            } else if (Character.isLowerCase(lastChar)) {
                if (lastChar == c && lastChar != nextC) {
                    flag = true;
                } else if (lastChar != c) {
                    flag = true;
                }
            } else if (Character.isDigit(lastChar) && c != nextC) {
                flag = true;
            }
        }

        return flag && checkInput(remain, c);
    }
}

三、测试

3ab4cd
aaabccccd
aa4b
aabbbb
caa4b
caabbbb
22aa
!error
2a4b
!error
4a5b22c
aaaabbbbbcccccccccccccccccccccc

你可能感兴趣的:(笔试题,压缩算法,字符串解压)