简体   繁体   中英

Reduce memory usage in the below anagram program - C#

Trying the Anagram checker by inputting paragraph and output is clear, but the memory limits exceeds the specified

This the code which i tried

using System;

class Program
{
    static void Main(string[] args)
    {

        string[] arr = (Punct(Console.ReadLine()).ToLower()).Split(' ');
        string a = string.Empty;
        System.Collections.Generic.Dictionary<string, string> dn = new System.Collections.Generic.Dictionary<string, string>(); // *2
        foreach (string s in arr)
        {
            string st = sort(s);
            if (dn.ContainsKey(st))
            {
                if (dn[st] != s)
                {
                    if (a.Contains(dn[st]))
                        a = a.Replace(dn[st], dn[st] + " " + s); // *1
                    else
                        a = a + dn[st] + " " + s + "\n";
                    dn[st] = s;
                }
            }
            else
                dn.Add(st, s);
        }
        Console.Write(a);
    }

    public static string sort(string s)
    {
        char[] chars = s.ToCharArray();
        Array.Sort(chars);
        return new string(chars);
    }

    public static string Punct(string s)
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        foreach (char c in s)
        {
            if (!char.IsPunctuation(c))
                sb.Append(c);
        }
        return sb.ToString();
    }
}

On checking with profiler, String function takes a lot of memory and other dictionary too, so, my question is how can i optimize the above code to a least memory, or any codes or declaration which i am using are unnecessary ?

Input:

Parts of the world have sunlight for close to 24 hours during summer. Dan had a strap on his head to identify himself as the leader and He wondered what kind of traps lay ahead of him.

Output:

parts strap traps
dan and

Few points I noticed:

  • Instead of loading whole file into memory, read it word-by-word. It might make things more complex, but it will reduce memory for big files. Not that it matters for example text you provided.
  • Instead of accumulating result output (in a), just save the words in dictionary itself, probably in the list, and output it after you run through whole file.
  • Try using Radix Tree instead of using dictionary.

I think my 2nd point here is most important in your case. 1st and 3rd point would matter if you had much bigger file with many more different words, but minimal "hits" of equal anagrams.

Try to minimize String operations, especially concatenation without StringBuilder. In addition, just use C# LINQ technology:

string input = Console.ReadLine();
string[] words = (Punct(input).ToLower()).Split(' ');

var anagramStrings = words
    .Distinct()
    .GroupBy(sort)
    .Where(anagrams => anagrams.Count() > 1)
    .Select(anagrams => String.Join(" ", anagrams));

string output = String.Join("\n", anagramStrings);

Console.Write(output);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM