计算无限字符串中字母的出现次数

Posted

技术标签:

【中文标题】计算无限字符串中字母的出现次数【英文标题】:Counting occurences of a Letter in an infinite String 【发布时间】:2019-04-05 05:39:53 【问题描述】:

我有一个名为s="abcac" 的字符串,它被无限重复了很多次。这意味着s 看起来像:s="abcacabcacabcacabcacabcac...."n 代表s 的子字符串。

例如,如果s="monday"n="10",我们考虑的子字符串将是finalString="mondaymond",因为无限字符串将是"mondaymondaymondaymonday...",而s的前10个字符是"mondaymond"

我正在尝试计算finalString 中字母“a”的出现次数。此代码运行正常,但是当 n>1000000 时程序将无法运行。

此外,如果我将nint 更改为long,则 for 循环在这种情况下将不起作用。

解决这个问题的方法是什么?

public static void main(String[] args)

            String s="abcac";
            int aCount=0;
            int n=1000;
            int j=0;


            char[] sCharArray=s.toCharArray();

            char[] finalString = new char[n];

            for(int i=0;i<n;i++)

                if(j==s.length())
                    j=0;

                finalString[i]=sCharArray[j];
                j++;


            


            for(int i=0; i<n;i++)
                if(finalString[i]=='a')
                    aCount++;
            


    System.out.println(aCount);

            

【问题讨论】:

【参考方案1】:

我建议找出基本字符串重复了多少次,并使用此信息计算字母的出现次数,以及最后额外子字符串的出现次数。例如:

String s = "monday";
int n = 10;
String chr = "a";

int baseNum = s.length() - s.replace(chr, "").length();
int baseCnt = (n / s.length()) * baseNum;
int index = n % s.length();
String left = s.substring(0, index);
int finalCnt = left.length() - left.replace(chr, "").length();
int totalCnt = baseCnt + finalCnt;

System.out.println("There were " + totalCnt + " letter " + chr + ".");

这里的基本思想是效率。我们实际上不需要创建和使用任意长度的字符串,因为我们知道它只是重复相同的子字符串。相反,我们可以只计算子字符串中出现的次数,然后根据子字符串重复的次数来预测总数。

【讨论】:

非常感谢。这是我正在寻找的纯“数学”算法!非常高效,没有循环或重复数组。 实际上这个解决方案不包括@yasserkabbout 在他的问题中提到的n 类型更改为long 的情况。 @ETO 我已将算法修改为 long。数学方法更好......你怎么看? @ETO 你是对的,但是String#length() 返回一个整数,而不是一个长整数,所以理论上来说,无限字符串不能有一个不适合整数的长度。无论如何,这个问题更多的是关于算法而不是你提出的观点。 @yasserkabbout 好吧,这三种解决方案在底层都有相同的数学方法。理论上s 的长度可以是一个非常大的数字(最大为 MAX_INT)。我的建议是在这种特殊情况下避免使用.substring.replace,因为在我的情况下,它们的总复杂度远远超过 O(n)。【参考方案2】:

正如其他答案中已经指出的那样,您不需要构建最终字符串。

这是我的解决方案:

public static void main(String[] args)
    String s = "abcacas";
    long n = 1000000;

    long count = getCount(s, n, 'a');
    System.out.println(count);


private long getCount(String str, long n, char c) 
    int length = str.length();

    long repeats = n / length;
    long reminder = n % length;

    long count = 0;
    for (int i = 0; i < length; i++) 
        if (str.charAt(i) == c) 
            count += repeats;
            if (i < reminder) 
                count++;
            
        
    
    return count;

【讨论】:

感谢您的贡献。我检查了我的 IDE 上的代码,但是它不起作用,因为 n 类型是整数。但是,我发现在您将变量类型更改为 long 后它现在可以工作了。【参考方案3】:

您不需要构造最终字符串。您只需计算s 字符串中“a”(或任何您想要的)的出现次数,并计算此s 重复的次数。毕竟,在提醒中计算“a”的出现次数。

long countInS = // count all occurances of 'a'
long repeats = n / s.length;
long reminder = n % s.length;
String sReminder = s.substring(reminder);
long countInReminder = // count all occurances of 'a' in sReminder 
long count = repeats * countInS + countInReminder;

无需浪费内存

【讨论】:

【参考方案4】:

我们可以通过在计算出现次数之前计算余数来进一步优化,并像这样使用它

import java.util.Scanner;
public class Main

    public static void main(String[] args)
    Scanner ip=new Scanner(System.in);
    String s=ip.next();
    int n=ip.nextInt();
    int res=0;
    int c=0,len=s.length(),cnt=0;
    for(;cnt<len;cnt++)
    if(s.charAt(cnt)=='a')
    c++;
    if(n%len!=0&&cnt==(n%len)-1)
    res=c;
    
    int mul=n/len;
    System.out.println((mul*c)+res);
    

【讨论】:

以上是关于计算无限字符串中字母的出现次数的主要内容,如果未能解决你的问题,请参考以下文章

华为机试:计算某字母出现次数

Oracle:一个查询,它计算字符串中所有非字母数字字符的出现次数

华为机试HJ2:计算某字母出现次数

python技巧 计算字符串中字母出现的次数并取出最大

华为机试题-计算字符出现次数

excel如何计算一行excel单元格中相同字符字母出现次数