【问题标题】:How would you find the initial letter with the most occurrences using recursion?如何使用递归找到出现次数最多的首字母?
【发布时间】:2013-05-27 18:05:19
【问题描述】:

给定一个分布在链表中的句子,其中链表中的每个项目都是一个单词,例如:

你好 -> 大家 -> 怎么样 -> 是 -> 你 -> 感觉 -> |

鉴于此列表已排序,例如:

是 -> 每个人 -> 感觉 -> 你好 -> 如何 -> 你 -> |

你会如何编写递归来找到句子中出现次数最多的首字母(在本例中是来自 Hello & How 的字母 H)?

【问题讨论】:

  • 在纸上你会怎么做?
  • 是什么让你认为递归是解决这个问题的最佳方法,或者这是一个练习/家庭作业?
  • 这就是练习:)
  • 请澄清“句子中出现次数最多的第一个字母”。 o 出现的次数远远超过 h...
  • @japreiss 似乎它必须是单词的第一个字母。唯一适用的字母是 A、E、F、H、H、Y。但这种说法非常具有误导性。

标签: algorithm recursion linked-list


【解决方案1】:

编辑:我已将代码更新为递归版本。

为了运行它,你调用

GetMostLetterRecursion(rootNode , '0', 0, '0', 0)

代码本身如下所示:

public char GetMostLetterRecursion(LinkedListNode<String> node, char currentChar, int currentCount, char maxChar, int maxCount)
{
    if (node == null) return maxChar;

    char c = node.Value[0];
    if (c == currentChar)
    {
        return GetMostLetterRecursion(node.Next, currentChar, currentCount++, maxChar, maxCount);
    }

    if(currentCount > maxCount)
    {
        return GetMostLetterRecursion(node.Next, c, 1, currentChar, currentCount);
    }

    return GetMostLetterRecursion(node.Next, c, 1, maxChar, maxCount);
}

【讨论】:

    【解决方案2】:

    解决方案 1

    遍历单词,记录每个字母开头的单词数。根据计数返回最受欢迎的字母(如果您使用优先级队列进行计数,则很容易)。

    这需要 O(n) 时间(单词数)和 O(26) 内存(字母表中的字母数)。

    解决方案 2

    按字母顺序对单词进行排序。循环单词。记录当前字母及其频率,以及迄今为止最流行的字母及其频率。在循环结束时,这是整个列表中最受欢迎的字母。

    这需要 O(n log n) 时间和 O(1) 内存。

    【讨论】:

    • 由于列表已排序,因此选项 2 为 O(n)。您可以在我的答案中看到代码
    【解决方案3】:

    保留一个数组来存储出现次数,并遍历链表一次进行计数。最后循环遍历数组以找到最高的一个。

    C 中的粗略草图:

    int count[26]={0};
    
    While ( head->next != NULL)
    {
      count[head->word[0] - 'A']++; // Assuming 'word' is string in each node
      head = head->next;
    }
    
    max = count[0];
    for (i=0;i<26;i++)
    {
      if(max<a[i])
        max = a[i];
    }
    

    您可以修改它以使用递归并处理小写字母。

    【讨论】:

      【解决方案4】:

      这是 Python 中的纯递归实现。我还没有测试过它,但它应该可以工作模数拼写错误或语法错误。我使用字典来存储计数,因此它也适用于 Unicode 单词。问题分为两个函数:一个是计算每个字母出现的次数,另一个是递归查找最大值。

      # returns a dictionary where dict[letter] contains the count of letter
      def count_first_letters(words):
      
          def count_first_letters_rec(words, count_so_far):
      
              if len(words) == 0:
                  return count_so_far
      
              first_letter = words[0][0]
      
              # could use defaultdict but this is an exercise :)
              try:
                  count_so_far[first_letter] += 1
              except KeyError:
                  count_so_far[first_letter] = 1
      
              # recursive call
              return count_first_letters_rec(words[1:], count_so_far)
      
          return count_first_letters(words, {})
      
      
      # takes a list of (item, count) pairs and returns the item with largest count.
      def argmax(item_count_pairs):
      
          def argmax_rec(item_count_pairs, max_so_far, argmax_so_far):
      
              if len(item_count_pairs) == 0:
                  return argmax_so_far
      
              item, count = item_count_pairs[0]
      
              if count > max_so_far:
                  max_so_far = count
                  argmax_so_far = item
      
              # recursive call
              return argmax_rec(item_count_pairs[1:], max_so_far, argmax_so_far)
      
          return argmax_rec(item_count_pairs, 0, None)
      
      
      def most_common_first_letter(words);
      
          counts = count_first_letters(words)
      
          # this returns a dictionary, but we need to convert to
          # a list of (key, value) tuples because recursively iterating
          # over a dictionary is not so easy
      
          kvpairs = counts.items()
          # counts.iteritems() for Python 2
      
          return argmax(kvpairs)
      

      【讨论】:

        【解决方案5】:

        我有一个长度为 26 的数组(作为英文字母,因此索引 1 用于 'a' 和 2 用于 'b' 等等。)。每次出现一个字母时,我都会增加它在数组中的值。如果该值超过最大数量,则更新最大值并将该字母作为最常出现的字母。然后我调用下一个节点的方法。

        这是Java代码:

        import java.util.LinkedList;
        
        
        public class MostOccurance {
            char mostOccured;
            int maxOccurance;
            LinkedList<String> list= new LinkedList<String>();
            int[] letters= new int[26];
        
        
         public void start(){
             findMostOccuredChar( 0, '0', 0);
         }
        
         public char findMostOccuredChar ( int node, char most, int max){
             if(node>=list.size())
                 return most;
             String string=list.get(node);
             if (string.charAt(0)== most)
                 {max++;
                 letters[Character.getNumericValue(most)-10]++; 
                 }
             else{
                 letters[Character.getNumericValue(most)-10]++;
                 if (letters[Character.getNumericValue(most)-10]++>max){
                     max=letters[Character.getNumericValue(most)-10];
                     most=string.charAt(0);
                 }
             }
             findMostOccuredChar( node++, most, max);
        
             return most;
              }
        
        
          }
        

        当然,您必须将每个单词添加到链接列表中。我没有这样做,因为我只是在展示一个示例。

        【讨论】:

          猜你喜欢
          • 2015-02-06
          • 2017-04-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-30
          • 1970-01-01
          • 1970-01-01
          • 2019-02-28
          相关资源
          最近更新 更多