递归版本