跟小D每日学口语

C# 压缩与解压字符串

 
2009-11-24 17:46

/*

* 题目:压缩字符串。如“abbcccddddeef”,压缩成“a1b2c3d4e2f1”

* 解题: 这个题目也是面试常见的题目。看似很简单,其实暗藏杀机。一般的想法就是,一边遍历,一边计数,然后将字符和计数器组合成新的字符串。

* 这个想法没有错,但是结果有漏洞。

* 等你写好算法,一般面试官会问以下两个问题中的一个:

* 1:按照你的算法,“11111111111122222222222”(十二个1和十一个2)压缩的结果是什么?

* 2: 按照你的算法, 压缩结果为“a101b3”的字符串,它原来是什么样的?

*

* 先回答第一个问题:很多人理所当然的回答就是:112211。下一个问题就来了:请问字符串“1221”压缩的结果是多少?

* 也是112211,这回你傻眼了吧?

* 第二个问题:按照原来的思路,“a101b3”原来的字符串应该是101个a,3个b。但是面试官会说:“a101b3”我可以理解为1个a,1个0,3个b。

*

* 以上两个问题都是出现在 压缩结果的二义性。既然有压缩算法,就会有解压算法,如果压缩结果有二义性,那就没办法解压得到唯一的字符串,那压缩算法就没有意义了。

*

* 好吧,现在你就得绞尽脑汁的改善你的算法,等你好不容易觉得改对了,面试管不置可否。他会说:你能不能再针对你的压缩算法,写一个对应的解压算法?

* 承蒙面试管看得起你,你就等着死伤千万细胞把。因为后面还有后着。

*

* 等你把解压算法写好了,他就会去验证你的算法,这里就是黑盒测试了,给你一个字符串,先让你压缩,再让你解压,看看结果还是不是原来的样子。

* 如果是,有可能是侥幸的,他会在尝试其他的字符串,如果能一直保持一致,恭喜你。如果不行,你就慢慢的找原因吧...

*

* 一场面试下来,会让你晚上回去做噩梦的...

*

* 有一个可行的方案,但不知道是不是最佳的,比如说11个a,按十进制压缩的话,应该压成a9a2,11个1,因该压成1912,这样解压的时候就没有二义性了。

*/

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace LearnCompressString

{

    class Program

    {

        static void Main(string[] args)

        {

            string str = "abbcccddddfffffffffffffffffffffg01122233333333333333))))*(&^&*^&*****#……—--";

            Console.WriteLine(str);

            string result = CompressString(str);

            Console.WriteLine(result);

            result = ExtractString(result);

            Console.WriteLine(result);

            Console.ReadKey();

        }

        //字符串压缩

        public static string CompressString(string str)

        {

            const int iMaxCount = 9;//常量,表示多少进制,如十进制的 a9 表示9a 十六进制的af表示15a。这里用十进制。

            StringBuilder stringBuilder = new StringBuilder();

            int countChar = 1;//计数器

            str = str.Trim() + " ";//为了防止在下面的循环中溢出,我在原来的字符串末尾加上了一个空格。

            for (int i = 0; i < str.Length - 1; i++)

            {

                if (str[i + 1] == str[i])//如果连续的字符相等

                {

                    countChar++;//计数器加一

                    if (countChar > iMaxCount)//如果计数器大于9,压入stringBuilder,比如,连续十个a,应该表示为:a9a1,而不是a10

                    {

                        stringBuilder.Append(str[i]);

                        stringBuilder.Append(iMaxCount.ToString());

                        countChar = 1;

                    }

                    continue;

                }

                else//如果不等,就将当前的字符和计数压入stringBuilder

                {

                    stringBuilder.Append(str[i]);

                    stringBuilder.Append(countChar.ToString());

                    countChar = 1;

                }

            }

            return stringBuilder.ToString();

        }

        //字符串解压

        public static string ExtractString(string str)

 

        {

            StringBuilder stringBuilder = new StringBuilder();

            for (int i = 0; i < str.Length; i = i + 2)

            {

                int countChar=(int)str[i+1]-(int)'0';//将记录字符字数的字符,如a9中的9转化为整型的9

                for (int j = 0; j < countChar; j++)

                    stringBuilder.Append(str[i]);

            }

            return stringBuilder.ToString();

        }

    }

}

posted @ 2010-07-14 12:32  简简单单幸福  阅读(8706)  评论(0编辑  收藏  举报