计算无限字符串中字母的出现次数
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 时程序将无法运行。
此外,如果我将n
从int
更改为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);
【讨论】:
以上是关于计算无限字符串中字母的出现次数的主要内容,如果未能解决你的问题,请参考以下文章