我已经为golang中的question提交了以下解决方案,但对于基本情况失败了。我无法弄清楚为什么会失败。
var answer[][]int
func hasPathSum(root *TreeNode, sum int, path []int){
if root == nil {
return
}
newPath := append(path, root.Val)
sum = sum - root.Val
if root.Left == nil && root.Right == nil && sum == 0 {
answer = append(answer, newPath)
fmt.Println(answer)
return
}
if root.Left != nil {
hasPathSum(root.Left, sum, newPath)
}
if root.Right != nil {
hasPathSum(root.Right, sum, newPath)
}
}
func pathSum(root *TreeNode, sum int) [][]int {
var path []int
answer = [][]int{}
hasPathSum(root, sum, path)
return answer
}
当我避免声明newPath
时,它将通过基本检查。像这样:
var answer[][]int
func hasPathSum(root *TreeNode, sum int, path []int){
if root == nil {
return
}
sum = sum - root.Val
if root.Left == nil && root.Right == nil && sum == 0 {
answer = append(answer, append(path, root.Val))
fmt.Println(answer)
return
}
if root.Left != nil {
hasPathSum(root.Left, sum, append(path, root.Val))
}
if root.Right != nil {
hasPathSum(root.Right, sum, append(path, root.Val))
}
}
func pathSum(root *TreeNode, sum int) [][]int {
var path []int
answer = [][]int{}
hasPathSum(root, sum, path)
return answer
}
我无法弄清楚两种解决方案之间的区别是什么。从递归的角度来看,这两种解决方案是相同的。此外,C ++中的similar solution通过了所有检查。
答案 0 :(得分:3)
发生此问题是因为切片引用了基础数组,并且如果有空间,index: ( 2 0 )
不会重新分配新数组。参见2
这意味着当您append
时,新切片有时会与append(path, root.Val)
共享后备阵列。可能是个问题,例如:
path
在这里,两个分支都可能使用相同的后备数组。这是一个问题,因为在执行第一个if root.Left != nil {
hasPathSum(root.Left, sum, append(path, root.Val))
}
if root.Right != nil {
hasPathSum(root.Right, sum, append(path, root.Val))
}
时,它可能会向hasPathSum
添加一个分片,但是该分片的基础数组仍可以在对answer
的第二次调用中使用更改其内容。
两个版本的代码都有相同的问题,但是因为第二个版本不太可能引起问题,因为如果hasPathSum
需要重新分配,那么您将在append(path, root.Val)
的两个分支中获得两个不同的副本。 。这意味着该错误将以较低的频率发生。
答案 1 :(得分:0)
我不确定#
# example Makefile based on OP version
# build 2 sets of obj with- or without feature flags
#
# $(shell touch foo.cu)
# regular, feature
TARGET_REG := reg-name
TARGET_FTR := ftr-name
DIR_REG := objreg
DIR_FTR := objftr
# $(shell mkdir -p $(DIR_REG) $(DIR_FTR)
CU_SRC := $(wildcard *.cu)
CU_OBJ := $(CU_SRC:%.cu=%-cu.o)
# $(info CU_SRC "$(CU_SRC)")
# $(info CU_OBJ "$(CU_OBJ)")
OBJ_REG := $(addprefix $(DIR_REG)/, $(CU_OBJ))
OBJ_FTR := $(addprefix $(DIR_FTR)/, $(CU_OBJ))
# $(info OBJ_REG "$(OBJ_REG)")
# $(info OBJ_FTR "$(OBJ_FTR)")
# added feature flags:
FTR_FLAGS := -abc
.PHONY: all clean
all: $(TARGET_REG) $(TARGET_FTR)
$(TARGET_REG): $(OBJ_REG)
@echo -e " link $@, OBJ $^\n"
$(TARGET_FTR): $(OBJ_FTR)
@echo -e " link $@, OBJ $^\n"
clean:
$(RM) foo* $(OBJ_REG) $(OBJ_FTR)
$(OBJ_FTR): CU_STUFF += $(FTR_FLAGS)
$(DIR_REG)/%-cu.o: %.cu
@echo build $< to $@, CU_STUFF \"$(CU_STUFF)\"
$(DIR_FTR)/%-cu.o: %.cu
@echo build $< to $@, CU_STUFF \"$(CU_STUFF)\"
,您可能只需要回答fmt.Println(answer)
。
这将通过:
return
这是LeetCode的Java解决方案,带有注释:
func pathSum(root *TreeNode, sum int) [][]int {
var paths [][]int
if root == nil {
return paths
}
if root.Left == nil && root.Right == nil {
if sum == root.Val {
return append(paths, []int{ root.Val })
}
return paths
}
for _, path := range pathSum(root.Left, sum - root.Val) {
paths = append(paths, append([]int{ root.Val}, path... ))
}
for _, path := range pathSum(root.Right, sum - root.Val) {
paths = append(paths, append([]int{ root.Val}, path... ))
}
return paths
}