首页 新闻 会员 周边 捐助

一个C#面试问题,要求是将字符串中重复字符从第二个开始都去掉,空格除外。

0
悬赏园豆:50 [已解决问题] 解决于 2014-05-16 16:18

某年某月某日的某个时候,去参加一次某个公司的C#技术面试。问题只是没有得到大小写是否要区分。

code如下,有人说这样写不对,我编译执行,觉得没问题。请大家帮忙看看:

犹豫这里格式很难把握,大家将就看。我只是从VS里面直接贴过来,看着太难看,所以折行显示了一下。应该不影响编译执行。

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace DeDup_Reverse

{    

class Program    

{        

public static void DeDupAndReverse(string str)        

{             char blank = ' ';            

StringBuilder sbDeDup = new StringBuilder();            

StringBuilder sbReverse = new StringBuilder();

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

{                

if ((!((sbDeDup.ToString()).Contains(str[index])) || (str[index].Equals(blank))))                 {                    

sbDeDup.Append(str[index]);                

}                

else                

{                    

continue;                

}            

}

            for (int index = sbDeDup.Length -1; index >= 0; index--)             {                

sbReverse = sbReverse.Append(sbDeDup[index]);            

}

            for (int index = 0; index < sbReverse.Length; index++)             {                

System.Console.Write(sbReverse[index]);            

}        

}

        public static void Main(string[] args)        

{            

string str = "Hello World";

            DeDupAndReverse(str);

            Console.ReadLine();        

}    

}

}

simonzhang的主页 simonzhang | 初学一级 | 园豆:157
提问于:2014-05-13 13:52
< >
分享
最佳答案
0
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 namespace DeDup_Reverse
 6 {
 7     class Program
 8     {
 9         public static void DeDupAndReverse(string str)
10         {
11             char blank = ' ';
12             StringBuilder sbDeDup = new StringBuilder();
13             StringBuilder sbReverse = new StringBuilder();
14             for (int index = 0; index < str.Length; index++)
15             {
16                 if ((!((sbDeDup.ToString()).Contains(str[index])) || (str[index].Equals(blank))))
17                 {
18                     sbDeDup.Append(str[index]);
19                 }
20                 else
21                 {
22                     continue;
23                 }
24             }
25             for (int index = sbDeDup.Length - 1; index >= 0; index--)
26             {
27                 sbReverse = sbReverse.Append(sbDeDup[index]);
28             }
29             for (int index = 0; index < sbReverse.Length; index++)
30             {
31                 System.Console.Write(sbReverse[index]);
32             }
33         }
34         public static void Main(string[] args)
35         {
36             string str = "Hello World";
37             DeDupAndReverse(str);
38             Console.ReadLine();
39         }
40     }
41 }

我说下我意见啊,说的不好不要介意
首先 void DeDupAndReverse(string str)你的这个函数不应该是 void 类型,应该是string类型,返回的是你处理过的字符串,这样通用性才高,而你呢,在这个方法里面还输出到了控制台,也就是说,你写的这个方法只有这个代码可以用,没有一点通用性。
其次,你用了 StringBuilder 这个类,说明你知道他比 string 的效率高,但是 StringBuilder 的效率像你这样用是不高的,你需要告诉 StringBuilder 初始长度的大小,这样他的效率才是最高的。
下面是我改的代码,逻辑方面用的是你写的,我没变过,但是代码的通用性和效率就高多了!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DeDup_Reverse
{
    public static class StringExtension
    {
        public static string DeDupAndReverse(this string str)
        {
            char blank = ' ';
            StringBuilder sbDeDup = new StringBuilder(str.Length);
            for (int index = 0; index < str.Length; index++)
            {
                if ((!((sbDeDup.ToString()).Contains(str[index])) || (str[index].Equals(blank))))
                {
                    sbDeDup.Append(str[index]);
                }
                else
                {
                    continue;
                }
            }
            StringBuilder sbReverse = new StringBuilder(sbDeDup.Length);
            for (int index = sbDeDup.Length - 1; index >= 0; index--)
            {
                sbReverse = sbReverse.Append(sbDeDup[index]);
            }
            return sbReverse.ToString();
        }
    }

    class Program
    {
        public static void Main(string[] args)
        {
            string str = "Hello World";
            Console.WriteLine(str.DeDupAndReverse());
            Console.ReadLine();
        }
    }
}

 

收获园豆:20
刘宏玺 | 专家六级 |园豆:14020 | 2014-05-13 14:18

哈哈,我也忽略了StringBuilder初始容量了。的确这是一个关键点,特别是字符串较长的时候。否则每次扩容*2都很耗时间的。

h82258652 | 园豆:293 (菜鸟二级) | 2014-05-13 14:23
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DeDupAndReverse
{
    class Program
    {
          public static string ProcessString(string input)
          {
             StringBuilder sb = new StringBuilder(input.Length);
              HashSet<char> hashSet=new HashSet<char>();
              foreach (var c in input)
             {
                  if (c == ' ')
                  {
                      sb.Append(c);
                 }
                 if (hashSet.Contains(c)==false)
                 {
                    sb.Append(c);
                    hashSet.Add(c);                 
                 }
             }
             return sb.ToString();
          }

          public static string DeDeup_Reverse(string toBeProcessed)
          {
              string toBeReversed = ProcessString(toBeProcessed);
              StringBuilder sbReversed = new StringBuilder(toBeReversed.Length);

              for (int i = toBeReversed.Length - 1; i >= 0; i--)
              {
                  sbReversed.Append(toBeReversed[i]);
              }

              return sbReversed.ToString();
          }

        public static void Main(string[] args)
        {
            string str = "Hello World, hello world";

            Console.WriteLine(DeDeup_Reverse(str));

            Console.ReadLine();
        }
    }
}

我更新了代码,大家再看看。

ProcessString 确实code简洁很多。非常感谢。吸收了下意见。看看这次还有什么问题么?

simonzhang | 园豆:157 (初学一级) | 2014-05-13 17:53

@simonzhang: 其实你的DeDeup_Reverse() ProcessString()这两个方法应该都是在Main()里面调用的,你在DeDeup_Reverse()调用rocessString()就说明:

给你一个字符串让你把他反转了你还要写一个方法

刘宏玺 | 园豆:14020 (专家六级) | 2014-05-13 22:10

@博客¥: 理解。不过当时面试的哥们说了,只希望调用一次。所以我这么写的。不过写在哪里,只是看需求了。实现上最好帮忙看看有没有继续可以改进的地方。我这次也就是学习了。不过非常感谢了。

simonzhang | 园豆:157 (初学一级) | 2014-05-14 09:15
其他回答(3)
0
 1         static string ProcessString(string input)
 2         {
 3             StringBuilder sb = new StringBuilder();
 4             HashSet<char> hashSet=new HashSet<char>();
 5             foreach (var c in input)
 6             {
 7                 if (c == ' ')
 8                 {
 9                     sb.Append(c);
10                 }
11                 if (hashSet.Contains(c)==false)
12                 {
13                     sb.Append(c);
14                     hashSet.Add(c);
15                 }
16             }
17             return sb.ToString();
18         }

个人简洁的解法。

主要觉得楼主不应该直接在里面打印结果,而应该作为返回值。

收获园豆:20
h82258652 | 园豆:293 (菜鸟二级) | 2014-05-13 14:13
0

嗯,HASH表匹配重复是比较块,我本来的想法是用链表.但链表长了之后,查找性能会变差,还是hash表比较块.

吴瑞祥 | 园豆:29449 (高人七级) | 2014-05-13 14:21
0
var resultStr= string.Join("", "abcdefgabcddddd".ToArray().Distinct());

忘了处理空值;

public class CustomComparer : IEqualityComparer<char>
        {
            public bool Equals(char x, char y)
            {
                if (x == ' ' || y == ' ')
                {
                    return false;
                }
                return x == y;
            }

            public int GetHashCode(char obj)
            {
                return 0;
            }
        }

写个自定义比较器就行。

var s = string.Join("","sss bbb ccc".ToArray().Distinct(new CustomComparer()));//s="a b c"

 

收获园豆:10
幻天芒 | 园豆:37207 (高人七级) | 2014-05-13 19:06

你这个使用微软封装的Distinct,请用原始的代码写嘛。

支持(0) 反对(0) wongdavid | 园豆:394 (菜鸟二级) | 2014-05-14 10:31

@wongdavid: 原始的一楼已经写了。换种思路而已。

支持(0) 反对(0) 幻天芒 | 园豆:37207 (高人七级) | 2014-05-14 13:38
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册