Algorithm 使用递归计算数组中的对象数

Algorithm 使用递归计算数组中的对象数,algorithm,recursion,Algorithm,Recursion,我对递归有一些问题,为了理解它,我试图为自己编造问题并解决它们。这个问题让我感到困惑: 将此视为字符串形式的输入: [[a,b,c],[[d]],[[e,f]],[g],h,i,[[j,[k,l]]]] 目标是找到列表中的事物总数以及它们自身的列表。对于本例,结果将是:12+10=22 请注意,输入不是数组,而是字符串。也不是a,b,。。。 任何东西都可以使用,如数字、字符串等。 [12345,0.34,["afv",24]] 这是我的想法,但我会提到为什么我不能实现它: 我们编写一个开始迭

我对递归有一些问题,为了理解它,我试图为自己编造问题并解决它们。这个问题让我感到困惑: 将此视为字符串形式的输入:

[[a,b,c],[[d]],[[e,f]],[g],h,i,[[j,[k,l]]]]
目标是找到列表中的事物总数以及它们自身的列表。对于本例,结果将是:
12
+
10
=
22
请注意,输入不是数组,而是字符串。也不是
a
b
,。。。 任何东西都可以使用,如数字、字符串等。

[12345,0.34,["afv",24]]
这是我的想法,但我会提到为什么我不能实现它:
我们编写一个开始迭代字符串的函数。它应该计算
[
]
之间的总数。每当函数到达
[
时,它就会调用自己迭代剩余的字符串。这样它就可以深入数组。
这些是我的问题:

  • 我不知道我的想法是否正确
  • 如果我的想法是正确的,那么基本情况是什么
  • 我如何确保它能计算出里面的所有东西,而不管它们是什么?(我的意思是,我如何确保它对数字、字符串等的处理是相同的)
  • 我认为函数体应该是这样的(我在这里使用java,但我认为语言在这里不是很重要):

    公共静态整数计数器(字符串a){
    整数和=0;
    //一些用于迭代字符串的代码
    //一些代码检查条件,如果需要,调用该方法
    //一些代码将对象数和数组数相加
    回报金额;
    }

  • 如果代码应该像我说的那样,那么如何填充正文?
    谢谢您的时间。

    根据您设计递归算法和输入大小的方式,您可能会遇到递归堆栈溢出的常见问题,其中递归非常深,内存空间不足

    这是一个不同的迭代pythonic解决方案,如果您不需要使用递归,但您应该能够将其转换为Java

    您希望增加以逗号分隔的每个项目的计数。但是,如果该元素具有']'字符,则您知道它是嵌入列表的一部分。通过计算右大括号和元素,可以得到总数

    更新了以处理带有嵌入逗号的字符串

    # Function for removing the chars between apostrophes
    def remove(s,c):
        while(s.find(c) != -1):
            i = s.find(c) # find the first instance of c but ' or " in our case
            i2 = s.find(c,i+1) # find the second instance
            s = s[0:i]+s[i2+1:] # Remove the string
            return s
        return s
    
    s = "[['a,b,c'],[1,2,3]]"
    s = s[:-1] # remove the last list char
    total = 0
    s = remove(s,'\'')
    s = remove(s,'"')
    l = s.split(',')
    for el in l:
        total+=1
        total+= el.count(']')
    print(total)
    

    由于您不关心解析列表的实际内容(为此您将实现一个递归下降解析器),因此可以实现一个简单的状态机

    这里是一个非常粗略的,部分的伪代码实现,目的是让您了解如何实现它。理想情况下,您会有更多的状态来检测语法错误:

    int lists, elements = 0;
    state = normal;
    foreach (char c in input)
    {
       switch state
          case normal:
            if (c == '[')
              lists++;
            else if (c == ']')
              // do nothing
            else if (c == ',')
              // do nothing (will only count [ and , on elements)
            else if (c == '"')
              elements++;
              state = quoted_element
            else
              elements++;
              state = element; 
            break;
    
          case quoted_element:
            if (c == '"')
              state = element;
            break;
    
          case element:
            if (c == '"' || c == '[')
              exception("Syntax error");
            else if (c == ",")
              elements++;
            else if (c == "]")
              state = normal;
            break;
    }
    

    下面是JavaScript中的一个递归,它可能会给您一些想法

    函数f(s){
    函数nextIndexTranstr(i){
    而(!(s[i]=“\”&&s[i-1]!=“\”)
    i++;
    返回i+1;
    }
    函数nextIndexafterNum(i){
    而(![”,“,”]“]包括(s[i]))
    i++;
    返回i;
    }
    //返回[nummarays、nummements、endIndex]
    //假定输入有效
    功能g(i、as、es){
    //基本情况
    如果(s[i]==”]“|i==s.length)
    返回[as,es,i];
    如果(s[i]==“,”)
    返回g(i+1,as,es);
    //单子
    如果(s[i]=“[”){
    常数[aas,ees,endIndex]=g(i+1,0,0);
    返回g(endIndex+1,as+1+aas,es+ees);
    }
    //字符串元素
    如果(s[i]=“\”)
    返回g(nextIndexafterStr(i+1),as,es+1);
    //数字或变量名元素
    返回g(nextIndexafterNum(i),as,es+1);
    }
    常数[as,es,z]=g(0,0,0);
    返回as+es;
    }
    var a=[12345,0.34,[“af\“v”,24];
    变量b=“[a,b,c],[d],[e,f],[g],h,i,[[j[k,l]]”;
    a=JSON.stringify(a);
    控制台日志(a);
    控制台日志(f(a));
    控制台日志(b);
    
    控制台。log(f(b));这可能过于简单化,考虑诸如<代码> [ a,b,c ] < < /代码>的情况。注意:这不包括元素可以用逗号嵌入字符串的情况,例如“Hello,那里”。"@Jae Yang tnx的解决方案,但我想知道递归的解决方案。另外,您必须使用java中的regx来拆分字符串,也可以使用算法来拆分字符串,但如果字符串的长度为10000个字符,我认为拆分字符串并将其放入数组或列表中不会非常省时。不要尝试所有操作同时,这将导致非常复杂的代码,你可能会丢失。第一步是把输入解析成一个抽象的语法树,它反映了结构,然后进行计数。“对不起,亨利,我只是一个业余爱好者,你能解释更多的细节吗?你的基本思想是正确的。ser'这是一个众所周知的算法。@IanMercer是的,有人告诉我这个名字,我搜索了它。但实际上我很难编写代码。尽管如果你真的不关心里面的内容,并且你确信输入格式正确,你可能只需要一个简单的状态机。状态1=正常。状态2=在某种情况下,状态3=在引用的内容中。读取每个字符,根据状态句柄计数,根据需要更改状态,…查找“有限状态机”。它是如何递归的?不是;请参阅问题的注释。如果您想要递归,请创建递归下降解析器,但对于指定的目标,您不需要它。