String 如何减少内存使用,搜索序列中的第k个字符?
问题陈述: 一位老师曾经说过:“好文章就是好文章就是好文章。” 因此,老师定义f0=“好文章就是好文章。” 为了使引语更有趣,老师定义fn=“好的写作是好的”+fn−1+“写作很好”+fn−1+“写得很好。”对所有人来说≥一, 例如,f1是:String 如何减少内存使用,搜索序列中的第k个字符?,string,algorithm,memory,out-of-memory,String,Algorithm,Memory,Out Of Memory,问题陈述: 一位老师曾经说过:“好文章就是好文章就是好文章。” 因此,老师定义f0=“好文章就是好文章。” 为了使引语更有趣,老师定义fn=“好的写作是好的”+fn−1+“写作很好”+fn−1+“写得很好。”对所有人来说≥一, 例如,f1是: 好文章就是好文章就是好文章。写作是好的写作是好的写作是好的写作。写得很好。 请注意,引号不是f1的一部分 老师想问q问题。每次她都想找到fn的第k个角色。 字符的索引从1开始。如果fn包含少于k个字符,则输出 在所有测试中 一,≤Q≤十, 0≤N≤三十 一
好文章就是好文章就是好文章。写作是好的写作是好的写作是好的写作。写得很好。
请注意,引号不是f1的一部分
老师想问q问题。每次她都想找到fn的第k个角色。
字符的索引从1开始。如果fn包含少于k个字符,则输出
在所有测试中
一,≤Q≤十,
0≤N≤三十
一,≤K≤231−一,
例如:
输入:
3
0 4
1 100
1 1111111
3
0 6
1 13
1 22
输出:
d
g
.
w
G
输入:
3
0 4
1 100
1 1111111
3
0 6
1 13
1 22
输出:
d
g
.
w
G
我的问题:
到目前为止,我所做的只是创建一个数组来存储f0到f31的预计算字符串
String[] f = new String[31];
f[0] = "Good writing is good writing is good writing.";
f[1] = "Good writing is good Good writing is good writing is good writing. writing is good Good writing is good writing is good writing. is good writing.";
for(int i = 2; i < 31; i++) {
f[i] = "Good writing is good " + f[i-1] + " writing is good " + f[i-1] + " is good writing.";
}
String[]f=新字符串[31];
f[0]=“好文章就是好文章就是好文章。”;
f[1]=“好文章就是好文章就是好文章。好文章就是好文章。好文章就是好文章。好文章就是好文章。好文章就是好文章。”;
对于(int i=2;i<31;i++){
f[i]=“好的写作是好的”+f[i-1]+“写作是好的”+f[i-1]+“是好的写作。”;
}
预计算最大值31后,我查询输入:
while(q-->0) {
int n = readInt();
int k = readInt();
System.out.println(f[n]);
if(f[n].length() < k) {
System.out.println(".");
} else {
System.out.println(f[n].charAt(k-1));
}
}
while(q-->0){
int n=readInt();
int k=readInt();
System.out.println(f[n]);
if(f[n].length()
现在的问题是,当我这样做的时候,我得到了一个内存不足的错误。这让我想到有一种更快更简单的方法来回答这个问题。我觉得有一种模式,但我可能错了。有什么想法吗?一个想法是确定第k个字符在添加的部分中的位置。为此,除了第k个字符外,我们可以使前一个调用返回其结果的长度,而不是结果本身。然后我们就可以决定kth落在什么地方。以下代码还返回字符串,但仅用于演示 您可以看到,在我们的函数中,
f(n,k)
,若我们确定第k个字符落在f(n-1)
的一个部分中,我们从k
中减去前面部分/s的长度,并从f(n-1,k-前缀的长度)
中获得kth
,因为这就像查找(新)kth-insidef(n-1)
。我们根据需要递归执行该搜索
JavaScript代码:
//返回[len\u fn,kth,fn]
函数f(n,k){
const f_0=“好文章就是好文章。”
常数len_0=f_0.length
const str_1=“好的写作是好的”
const str_2=“写作很好”
const str_3=“是一篇好文章。”
常数len_1=str_1.length
常量len_2=str_2.length
常量len_3=str_3.length
如果(n==0)
返回[len_0,f_0[k-1],f_0]
常数[len_fn1,kth1,fn1]=f(n-1)
常数fn=str_1+fn1+str_2+fn1+str_3
常数len_fn=len_1+len_fn1+len_2+len_fn1+len_3
常数pos_fn1_2=长度1+len_fn1+len_2
if(k)请注意,每个字符串的长度是前一个字符串的两倍以上。f30的长度为几十GB。@BenVoigt谢谢你,但再一次,你认为有更有效的方法吗?我建议改为:建立一个fi长度表,即字符串中前一个字符串(fi-1)所在的点第一次出现,第二次出现的点。@BenVoigt by fi你是说fn吗?我是说f[I]
就像在循环准备中一样,而不是f[n]
wheren=readInt()
你能解释一下这些代码部分吗?我对JavaScriptconst[len_fn1,kth1,fn1]=f不太熟悉(n-1)
和console.log(JSON.stringify(fn.split(“”).map((x,i)=>[i+1,x]))
@TimothyW553当然。const[len_fn1,kth1,fn1]=f(n-1)
:由于函数f
返回一个由三项组成的数组,该数组会立即将它们分配给三个变量,len_fn1,kth1,fn1
。您询问的第二个变量,console.log(JSON.stringify(fn.split(“”.map((x,i)=>[i+1,x]))
将长字符串结果fn
记录为元组列表,这样我们可以看到每个字符的索引,更容易确认函数返回的答案是否正确。@TimothyW553我稍微修改了代码,在结果之后手动记录索引字符串,而不是作为递归的一部分。