使用递归计算更大数组中子数组的出现次数
Count occurences of a subarray in a bigger array using recursion
我必须编写一个 递归函数来计算短数组 s2 在较大数组 s1 中出现的次数而不重叠 。我可以使用不止一个可以帮助我的函数,但它们必须都是递归函数。例如:
#define n 10
#define p 2
s1[n]={0,2,3,23,54,1,8,23,54,1}
s2[p]={23,54}
OUTPUT: 2 (we see s2 two times in s1)
我考虑编写一个递归函数来告诉我是否至少有一次出现,然后在另一个计算出现次数的递归函数中使用此函数。所以这就是我写的:
//Initially pos1=0 and pos2=0
int find(int *s1,int *s2,int pos1,int pos2){
if(n-pos1<p-pos2)
return 0;
if(*(s1+pos1)==*(s2+pos2)){
if(pos2==p-1)
return pos1;
else{
if(find(s1,s2,pos1+1,pos2+1))
return pos1;
}
}
return find(s1,s2,pos1+1,0);
}
然后我写了第二个应该计算出现次数的递归函数:
// Initially occ(s1,s2,0);
int occ(int *s1,int *s2,int memo){
if(memo==n){ //end of s1
return 0;
}
else{
if(find(s1+memo,s2,memo,0))
return 1+occ(s1+memo,s2,memo+p);
}
}
其背后的思想是验证是否至少有一次出现,如果有出现则统计它并对s1的剩余部分重新进行验证,直到结束。
问题是第二个函数的代码根本不起作用,我找不到修复它的方法。
那么如何使用上面编写的函数 find() 编写第二个计算出现次数的递归函数?
来自
It works if s1[n]={0,0,0,3,4,0,0,0,3,4,0,0,0,3,4,0,0,0,3,4};
and s2[p]={3,4}
. Indeed the output is 4. But if s2[p]={0,0}
the output is 0
which is not correct.
这是因为,当s2={0,0}
find()
函数returnspos1 = 0
as子集出现在最beginning 因此在 occ()
函数中 if(find(s1+memo,s2,memo,0)) 评估为 false 并终止函数而不返回任何值,这会调用 未定义的行为
这可以通过返回 0
以外的任何数字来避免,但它不能是数组中任何有效的位置值 s1
.
因为位置不能是负数,我选择了-1
请参阅以下代码以了解如何避免它:
#include <stdio.h>
#define n 10
#define p 2
int s1[n]={0,2,3,23,54,1,8,23,54,1};
int s2[p]={23,54};
//find function
int find(int* s1,int* s2,int pos) //only used `pos` instead of `pos1`, removed `pos2`
{
if(pos > n-2)
{
return -1; //returns `-1` upon reaching the end of the code
}
if(*(s1+pos) == *(s2+0)) //check at `s1+pos`
{
if(*(s1+(pos+1)) == *(s2+1)) //check next element `s1+pos+1`
{
return pos; //if both true return `pos`
}
else
{
return find(s1,s2,pos+1); //else recursively find in the rest of the array
}
}
return find(s1,s2,pos+1); // recursively find in the rest of the array
}
//occurence function
int occ(int *s1, int *s2,int memo)
{
if(memo == -1) //if end of the array, end adding occurrences by returning 0
{
return 0;
}
else
{
memo = find(s1, s2, memo); //scan position into memo
if(memo != -1) //if not end of the array i.e, `-1` add to occurrence
{
return 1+occ(s1,s2,memo+2);
}
else
{
return 0; //else return 0 and recursion would end in next call as memo is -1
}
}
}
//main function
int main(void)
{
printf("%d",occ(s1,s2,0)); //just to see the output
}
输出:
2 //true as {23,54} occur two times
当输入是:(编译时)
#define n 20
#define p 2
s1[n]={0,0,0,3,4,0,0,0,3,4,0,0,0,3,4,0,0,0,3,4};
s2[p]={0,0};
输出:
4 //true as {0,0} occurs at 0,5,10,16
我必须编写一个 递归函数来计算短数组 s2 在较大数组 s1 中出现的次数而不重叠 。我可以使用不止一个可以帮助我的函数,但它们必须都是递归函数。例如:
#define n 10
#define p 2
s1[n]={0,2,3,23,54,1,8,23,54,1}
s2[p]={23,54}
OUTPUT: 2 (we see s2 two times in s1)
我考虑编写一个递归函数来告诉我是否至少有一次出现,然后在另一个计算出现次数的递归函数中使用此函数。所以这就是我写的:
//Initially pos1=0 and pos2=0
int find(int *s1,int *s2,int pos1,int pos2){
if(n-pos1<p-pos2)
return 0;
if(*(s1+pos1)==*(s2+pos2)){
if(pos2==p-1)
return pos1;
else{
if(find(s1,s2,pos1+1,pos2+1))
return pos1;
}
}
return find(s1,s2,pos1+1,0);
}
然后我写了第二个应该计算出现次数的递归函数:
// Initially occ(s1,s2,0);
int occ(int *s1,int *s2,int memo){
if(memo==n){ //end of s1
return 0;
}
else{
if(find(s1+memo,s2,memo,0))
return 1+occ(s1+memo,s2,memo+p);
}
}
其背后的思想是验证是否至少有一次出现,如果有出现则统计它并对s1的剩余部分重新进行验证,直到结束。
问题是第二个函数的代码根本不起作用,我找不到修复它的方法。
那么如何使用上面编写的函数 find() 编写第二个计算出现次数的递归函数?
来自
It works if
s1[n]={0,0,0,3,4,0,0,0,3,4,0,0,0,3,4,0,0,0,3,4};
ands2[p]={3,4}
. Indeed the output is 4. But ifs2[p]={0,0}
the output is0
which is not correct.
这是因为,当
s2={0,0}
find()
函数returnspos1 = 0
as子集出现在最beginning 因此在occ()
函数中 if(find(s1+memo,s2,memo,0)) 评估为 false 并终止函数而不返回任何值,这会调用 未定义的行为这可以通过返回
0
以外的任何数字来避免,但它不能是数组中任何有效的位置值s1
.因为位置不能是负数,我选择了
-1
请参阅以下代码以了解如何避免它:
#include <stdio.h>
#define n 10
#define p 2
int s1[n]={0,2,3,23,54,1,8,23,54,1};
int s2[p]={23,54};
//find function
int find(int* s1,int* s2,int pos) //only used `pos` instead of `pos1`, removed `pos2`
{
if(pos > n-2)
{
return -1; //returns `-1` upon reaching the end of the code
}
if(*(s1+pos) == *(s2+0)) //check at `s1+pos`
{
if(*(s1+(pos+1)) == *(s2+1)) //check next element `s1+pos+1`
{
return pos; //if both true return `pos`
}
else
{
return find(s1,s2,pos+1); //else recursively find in the rest of the array
}
}
return find(s1,s2,pos+1); // recursively find in the rest of the array
}
//occurence function
int occ(int *s1, int *s2,int memo)
{
if(memo == -1) //if end of the array, end adding occurrences by returning 0
{
return 0;
}
else
{
memo = find(s1, s2, memo); //scan position into memo
if(memo != -1) //if not end of the array i.e, `-1` add to occurrence
{
return 1+occ(s1,s2,memo+2);
}
else
{
return 0; //else return 0 and recursion would end in next call as memo is -1
}
}
}
//main function
int main(void)
{
printf("%d",occ(s1,s2,0)); //just to see the output
}
输出:
2 //true as {23,54} occur two times
当输入是:(编译时)
#define n 20 #define p 2 s1[n]={0,0,0,3,4,0,0,0,3,4,0,0,0,3,4,0,0,0,3,4}; s2[p]={0,0};
输出:
4 //true as {0,0} occurs at 0,5,10,16