求助:如何递归统计嵌套Vector中的唯一对象?求代码实现指导
搞定扩展家族人数统计的递归逻辑
嘿,我来帮你梳理下之前代码里的问题,以及怎么优化出更可靠的实现~
先看你最初代码的核心问题
你第一次写的代码里,最大的bug出在for循环里的提前return:
for (Person familyMember : person.getFamily()) { return lineage.size() + getExtendedFamily(familyMember); }
这个return语句会在遍历第一个家庭成员时就直接跳出循环、返回结果,后面的家庭成员完全没机会被处理。比如你的示例里,Mike的family有Pete和John,但代码只会处理Pete,John和Amy的分支根本不会被统计,这就导致结果肯定不对。
正确的递归思路(无全局状态更可靠)
其实递归统计这类图结构(家族关系本质是无向图)的节点数,核心是避免重复统计,同时遍历所有关联节点。最好的方式是把已访问的集合作为递归参数传递,这样不用依赖全局的lineage或counter,避免多次调用时的状态污染:
// 对外暴露的方法,不用关心内部细节 public int getExtendedFamily(Person person) { // 第一次调用时初始化空的已访问集合 return countUniqueMembers(person, new HashSet<>()); } // 内部递归方法,负责核心统计逻辑 private int countUniqueMembers(Person person, Set<Person> visited) { // 如果已经统计过这个人,直接返回0,不重复计数 if (visited.contains(person)) { return 0; } // 标记当前人员为已访问,先算上自己(+1) visited.add(person); int total = 1; // 递归遍历每个家庭成员,累加他们的扩展家族人数 for (Person familyMember : person.getFamily()) { total += countUniqueMembers(familyMember, visited); } return total; }
这个实现的优势:
- 没有全局变量,多次调用
getExtendedFamily不会互相干扰 - 用
HashSet替代Vector做已访问标记,contains()方法的效率从O(n)提升到O(1),家族人数多的时候差距明显 - 逻辑清晰:每遇到一个新成员就+1,然后递归统计他的所有关联成员,自动去重
对你更新后代码的点评
你更新后的代码已经解决了“提前return”的问题,能遍历所有家庭成员了,但还有几个需要优化的点:
- counter初始值问题:如果
counter初始是0,那添加Mike后应该先把counter设为1(因为要包含自己),不然你的示例里会得到3而不是4 - 全局变量的隐患:如果多次调用这个方法,
lineage和counter的状态不会自动重置,比如先统计Mike的家族,再统计Amy的,结果会包含之前的所有人 - 冗余判断:for循环里的
!lineage.contains(family_member_)其实没必要,因为递归方法开头已经会判断是否已访问,重复判断纯属多余
伪代码版本(如果需要更抽象的逻辑)
函数 countExtendedFamily(当前人员, 已访问集合): 如果 当前人员 在已访问集合中: 返回 0 将 当前人员 加入已访问集合 计数 = 1 // 统计自己 对于 当前人员 的每个家庭成员: 计数 += countExtendedFamily(家庭成员, 已访问集合) 返回 计数
内容的提问来源于stack exchange,提问作者benjay_uk
相关产品推荐
相关产品推荐

