Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm Golang Slice-Java Arraylist-递归回溯-经典算法集在Golang中无法按预期工作_Algorithm_Go_Recursion_Slice_Backtracking - Fatal编程技术网

Algorithm Golang Slice-Java Arraylist-递归回溯-经典算法集在Golang中无法按预期工作

Algorithm Golang Slice-Java Arraylist-递归回溯-经典算法集在Golang中无法按预期工作,algorithm,go,recursion,slice,backtracking,Algorithm,Go,Recursion,Slice,Backtracking,我试图在Golang中使用递归和回溯来解决功率集问题: 给定一组不同的整数nums,返回所有可能的子集(幂集) 注意:解决方案集不得包含重复的子集。 例子: 输入:nums=[1,2,3] 输出: 这是一个典型的问题,通过使用下面的Java代码进行递归和回溯来解决: public List<List<Integer>> subsets(int[] nums) { List<List<Integer>> list = new Array

我试图在Golang中使用递归和回溯来解决功率集问题:

给定一组不同的整数nums,返回所有可能的子集(幂集) 注意:解决方案集不得包含重复的子集。 例子: 输入:nums=[1,2,3] 输出:

这是一个典型的问题,通过使用下面的Java代码进行递归和回溯来解决:

public List<List<Integer>> subsets(int[] nums) {
       List<List<Integer>> list = new ArrayList<>();
       backtrack(list, new ArrayList<>(), nums, 0);
     return list;
}

问题是tmp切片引用被保持,并且当回溯线

 tmp = tmp[0:len(tmp)-1]
执行时,它引用最近在结果中添加的相同tmp片。理想情况下,不应触摸结果切片。但看起来,由于切片重新引用相同的tmp,最终将把答案留给[]

我在GoLang真的很难做到这一点。

切碎内部构件

切片是数组段的描述符。它由一个指针组成 对于阵列,段的长度及其容量(最大值 段的长度)

您正在
result
中添加
tmp
,然后修改
tmp
,这意味着循环中
tmp
的上次修改数据将存储在
result

添加到
tmp
时存储一个新变量并传递它。现在您不需要在追加后删除,因为您使用的是一个新变量。递归调用时使用
i+1

func powerSubsetsDFS(nums []int, tmp []int, idx int, result [][]int) [][]int {
   result = append(result,tmp)
   for i:=idx;i<len(nums);i++{
     tmp2 := append(tmp, nums[i]) // store in a new variable
     result = powerSubsetsDFS(nums,tmp2,i+1,result)
   }
   return result;
}

func powerSubSets(nums []int){
   result :=[][]int{}
   tmp:=[]int{}
   result = powerSubsetsDFS(nums,tmp, 0, result)
   fmt.Println("Final Result ",result)
}
func powerSubsetsDFS(nums[]int、tmp[]int、idx int、result[]int][]int){
结果=追加(结果,tmp)

对于i:=idx;i所以,正如您所提到的,问题在于使用slice的方式。slice的大小为3个字(对于64位机器,1个字=8字节(64位)

第一个单词指向切片的第一个元素,第二个单词存储切片的长度,第三个单词存储切片的容量。您可以阅读有关切片的更多信息(一篇初学者友好的文章)

因此,正如您已经知道的那样,您将引用附加到tmp中的值,而不是temp中值的副本

问题的解决方案很简单,创建一个tmp副本并将该副本添加到结果切片中

tmpcpy := make([]int, len(tmp))
copy(tmpcpy, tmp)
result = append(result,tmpcpy)

因此,如果您更改tmp slice,结果中的值将不会受到影响,谢谢。这也有帮助。我犯了理解slice的基本错误。最终,它是一个参考。另外,如果您查看java代码,该代码也正在创建一个新的列表,添加到result中--list.add(new ArrayList(tempList)请澄清您的accual问题是使用idx+1而不是i+1,然后您不需要复制整个数组,只需追加并存储在新变量中,追加在新变量中不会每次都创建新切片,
func powerSubsetsDFS(nums []int, tmp []int, idx int, result [][]int) {
   result = append(result,tmp)
   fmt.Println("result idx ",idx,result)
   for i:=idx;i<len(nums);i++{
     tmp = append(tmp,nums[i])
     powerSubsetsDFS(nums,tmp,idx+1,result)
     fmt.Println(" subract ", idx , tmp)
     tmp = tmp[0:len(tmp)-1]
     fmt.Println(" subract after  ", idx , tmp)
}
    result idx  0 [[]]
result idx  1 [[] [1]]
result idx  2 [[] [1] [1 2]]
result idx  3 [[] [1] [1 2] [1 2 3]]
 subract  2 [1 2 3]
 subract after   2 [1 2]
 subract  1 [1 2]
 subract after   1 [1]
 tmp = tmp[0:len(tmp)-1]
func powerSubsetsDFS(nums []int, tmp []int, idx int, result [][]int) [][]int {
   result = append(result,tmp)
   for i:=idx;i<len(nums);i++{
     tmp2 := append(tmp, nums[i]) // store in a new variable
     result = powerSubsetsDFS(nums,tmp2,i+1,result)
   }
   return result;
}

func powerSubSets(nums []int){
   result :=[][]int{}
   tmp:=[]int{}
   result = powerSubsetsDFS(nums,tmp, 0, result)
   fmt.Println("Final Result ",result)
}
tmpcpy := make([]int, len(tmp))
copy(tmpcpy, tmp)
result = append(result,tmpcpy)