सी #: दोहराया स्ट्रिंग

Aug 20 2020

HackerRank से "दोहराया स्ट्रिंग" चुनौती:

लीला में एक स्ट्रिंग है, \ _$s\$अंग्रेजी के छोटे अक्षरों में, जिसे उसने कई बार दोहराया।

एक पूर्णांक दिया, \$n\$, खोजने के लिए और पत्र की संख्या एक के प्रिंट पहले में \$n\$ लीला के अनंत तार के अक्षर।

उदाहरण के लिए, यदि स्ट्रिंग \$s=abcac\$और \ _$n=10\$, उप स्ट्रिंग हम मानते हैं कि \$abcacabcac\$पहला \ _$10\$उसके अनंत तार के पात्र। वहाँ हैं \$4\$ उप-स्ट्रिंग में घटनाएँ।

टेस्ट केस 1:

        string input = "aba";
        long n = 10;

टेस्ट केस 2:

        string input = "a";
        long n = 1000000000000;

मेरा समाधान:

        string input = "aba";
        long n = 10;
        long numAs = input.Count(c => c.Equals('a'));

        if (input.Length == 0)
        {
            return 0;
        }

        long rem = n % input.Length;
        long reps = (n - rem) / input.Length;
        long count = reps * numAs;

        string sRem = input.Substring(0, (int)rem);

        if (rem != 0)
        {
            count += sRem.Count(c => c.Equals('a'));
        }

परिणाम 7 और 1000000000000 होना चाहिए। इस समाधान ने हैकररैंक पर सभी परीक्षण मामलों को पारित किया। यह अन्य समाधानों पर आधारित है, विशेष रूप से एक मैंने अप वोट दिया है।

जवाब

4 MartinVerjans Aug 20 2020 at 21:46
  1. क्या आपको इनपुट को मान्य करने की आवश्यकता है?

यदि हां, तो आपको सभी मामलों का परीक्षण करना चाहिए:

  • इनपुट शून्य हो सकता है
  • इनपुट एक खाली स्ट्रिंग हो सकता है
  • n नकारात्मक या 0 हो सकता है
  1. चर नाम

चर नाम महत्वपूर्ण हैं, वे कोड को बेहतर ढंग से समझने में मदद करते हैं। आपको उन्हें यथासंभव छोटा नहीं बनाना है। खासकर जब आपके पास VisualStudio जैसा एक IDE होता है जो आपको InteliSense के साथ उचित एक का चयन करने में मदद करेगा।

  • numAs -> एकाउंट
  • रेम -> शेष
  • प्रतिनिधि -> दोहराव
  • sRem -> शेष
  1. तेजी से असफल

आमतौर पर एक विधि "जितनी जल्दी हो सके" छोड़ना बेहतर होता है। इसलिए आप कोई भी कार्य करने से पहले इनपुट सत्यापन करना चाहते हैं और यदि यह मान्य नहीं है तो विधि से बाहर निकलें। उसी तरह, यदि आपका शेष 0 है, तो आप अपना परिणाम तुरंत वापस कर सकते हैं।

  1. पूर्णांक विभाजन

अपने पुनरावृत्ति की गणना करने के लिए, आप शेष को n से घटाते हैं। यदि आप C # में पूर्णांक विभाजन की जाँच करते हैं, तो आपको निम्न करने की आवश्यकता नहीं है:

long repetitions = n / input.length;
  1. Linq का उपयोग करें

Tinstaafl समाधान के अनुसार , आप एक चर और एक लाइन को बचाने के लिए Linq का उपयोग कर सकते हैं:

count += remainderString.Take((int)remainder).Count(c => c.Equals('a'));

तो, सभी में, आप प्राप्त करते हैं:

long aCount = input.Count(c => c.Equals('a'));

if (input == null || input.Length == 0 || n <= 0)
{
    return 0;
}

long repetitions = n / input.Length;
long remainder = n % input.Length;
long count = repetitions * aCount;

if (remainder == 0)
{
    return count;
}

return count + remainderString.Take((int)remainder).Count(c => c.Equals('a'));
2 tinstaafl Aug 20 2020 at 05:06

मुझे सुधार करने के लिए बहुत कुछ नहीं दिख रहा है। हालाँकि, मैंने कुछ चीजों पर ध्यान दिया:

शॉर्टकट सशर्त:

if (input.Length == 0)
{
    return 0;
}

आपके कोड में बहुत बाद की पहली बात होनी चाहिए input

इसी तरह से:

string sRem = input.Substring(0, (int)rem);

if (rem != 0)
{
    count += sRem.Count(c => c.Equals('a'));
}

आपको उस स्ट्रिंग की आवश्यकता नहीं है जब तक कि rem0 नहीं है, इसलिए इसे सशर्त ब्लॉक में शामिल करें। और भी बेहतर, LINQ एक्सटेंशन का उपयोग करें, Takeऔर एक स्टेटमेंट में सब कुछ करें:

if (rem != 0)
{
    count += sRem.Take((int)rem).Count(c => c.Equals('a'));
}
2 iSR5 Aug 21 2020 at 07:25

अन्य उत्तरों के समान अंक, हालांकि इसका एक सरल समाधान है, आप बस Aखाली स्ट्रिंग के साथ बदल सकते हैं , और दोनों तारों की लंबाई की तुलना कर सकते हैं, जो आपको ए की संख्या देगा।

यहाँ एक उदाहरण है :

public static long RepeatedString(string s, long n)
{
    if (string.IsNullOrWhiteSpace(s) || n <= 0) { return 0; }
    
    // Local function that would return the number of A's 
    long CountA(string input) => input.Length - input.Replace("a", "").Length;
    
    var aCount = CountA(s);
    
    var reminder = n % s.Length; 
    
    var repetition = (n - reminder) / s.Length;
    
    var count = repetition * aCount;

    var reminderStr = s.Substring(0, (int)reminder);
    
    var result = count + CountA(reminderStr);
    
    return result;
}
1 Noname Aug 22 2020 at 01:50

मैं जो पहले से ही लिखा गया है, उसके अलावा बहुत कुछ नहीं जोड़ सकता, जब यह प्रदर्शन की बात आती है, तो आप अक्सर लिनक ( long numAs = input.Count(c => c.Equals('a'));) को अधिक पारंपरिक forया whileलूप की तुलना में धीमा होने के लिए पाएंगे । लेकिन अगर आप Linq पर जोर देते हैं, तो आप सभी को पसंद कर सकते हैं:

long CountChars(string data, long length, char c = 'a')
{
  if (string.IsNullOrEmpty(data) || length <= 0) return 0;

  long repetitions = length / data.Length;
  long remSize = length % data.Length;

  return data
    .Select((ch, i) => (ch, i))
    .Where(chi => chi.ch == c)
    .Sum(chi => chi.i < remSize ? repetitions + 1 : repetitions);
}

यहां उस ओवरलोड का उपयोग किया जाता है जो Select()प्रत्येक तत्व के साथ इंडेक्स को एक मूल्य टपल को मैप करने के लिए प्रदान करता है, जिसमें से फ़िल्टर करना संभव है 'a'और अंत में पुनरावृत्ति को गाया जाता है: यदि इंडेक्स अनुस्मारक के आकार से कम है तो repetitions + 1चाहिए नहीं तो केवल प्रत्येक के लिए repetitions पाया 'a'


while-लूप का उपयोग कर एक पारंपरिक दृष्टिकोण - अनिवार्य रूप से ऊपर के रूप में एक ही दृष्टिकोण का उपयोग कर की तरह लग सकता है:

long CountChars(string data, long length, char c = 'a')
{
  if (string.IsNullOrEmpty(data) || length <= 0) return 0;

  long count = 0;
  long repetitions = length / data.Length + 1; // + 1 for the possible extra 'a' in the reminder
  long remSize = length % data.Length;

  int i = 0;

  while (i < remSize)
  {
    if (data[i++] == c)
      count += repetitions;
  }

  repetitions--;
  while (i < data.Length)
  {
    if (data[i++] == c)
      count += repetitions;
  }

  return count;
}

इस दृष्टिकोण के साथ स्ट्रिंग s( data) केवल एक बार पार्स की जाती है।