为了账号安全,请及时绑定邮箱和手机立即绑定

切片附加有奇怪的行为

切片附加有奇怪的行为

Go
三国纷争 2022-06-27 09:26:33
有人可以向我解释为什么 temp 的值决定在最后一个输出行上更改,即使 temp 只是列表数组的副本?func subsets(nums []int) [][]int {        if len(nums) == 0 {        return [][]int{[]int{}}    }        list := [][]int{[]int{nums[0]}}        for _, n := range nums[1:]{        list = append(list, []int{n})        temp := list[:len(list)-1]        fmt.Println(temp)        for _, arr := range temp {            arr = append(arr, n)            list = append(list, arr)        }               fmt.Println(temp)        fmt.Println("  ")    }        list = append(list, []int{})    return list    }output:[[1]][[1]]  [[1] [2] [1 2]][[1] [2] [1 2]]  [[1] [2] [1 2] [3] [1 3] [2 3] [1 2 3]][[1] [2] [1 2] [3] [1 3] [2 3] [1 2 3]]  [[1] [2] [1 2] [3] [1 3] [2 3] [1 2 3] [4] [1 4] [2 4] [1 2 4] [3 4] [1 3 4] [2 3 4] [1 2 3 4]][[1] [2] [1 2] [3] [1 3] [2 3] [1 2 3] [4] [1 4] [2 4] [1 2 4] [3 4] [1 3 4] [2 3 4] [1 2 3 5]]
查看完整描述

2 回答

?
慕丝7291255

TA贡献1859条经验 获得超6个赞

实际上,您正在复制切片,而不是数组。切片是数组段的描述符。它由指向数组的指针、段的长度及其容量(段的最大长度)组成。这意味着,您只是在创建切片标题的副本。底层数组仍然是共享的。 https://blog.golang.org/slices-intro


查看完整回答
反对 回复 2022-06-27
?
PIPIONE

TA贡献1829条经验 获得超9个赞

这是 Go 中数组和切片的一个非常常见的问题(这与 Python 和 JavaScript 中的不同)。你会习惯的,这个答案也已经解释过了。


当然,这里也解释了解决方案,我想你会知道它是如何工作的。


这将使用回溯传入 Go (实现起来更简单):


func subsets(nums []int) [][]int {

    subs := make([][]int, 0)

    backtrack(nums, 0, nil, &subs)

    return subs

}


func backtrack(nums []int, index int, sub []int, subs *[][]int) {

    if index == len(nums) {

        *subs = append(*subs, append([]int{}, sub...))

        return

    }


    backtrack(nums, index+1, sub, subs)

    backtrack(nums, index+1, append(sub, nums[index]), subs)

}

同样在Java中,


public final class Solution {

    public static final List<List<Integer>> subsets(

        final int[] nums

    ) {

        List<List<Integer>> subs = new ArrayList<>();

        Arrays.sort(nums);

        backtrack(subs, new ArrayList<>(), nums, 0);

        return subs;

    }


    private static void backtrack(

        final List<List<Integer>> subs, 

        final List<Integer> sub, 

        final int[] nums, 

        final int start

    ) {

        subs.add(new ArrayList<>(sub));


        for (int index = start; index < nums.length; index++) {

            sub.add(nums[index]);

            backtrack(subs, sub, nums, index + 1);

            sub.remove(sub.size() - 1);

        }

    }

}

迭代地,它会去(例如,使用 C++):


// The following block might trivially improve the exec time;

// Can be removed;

static const auto __optimize__ = []() {

    std::ios::sync_with_stdio(false);

    std::cin.tie(NULL);

    std::cout.tie(NULL);

    return 0;

}();



// Most of headers are already included;

// Can be removed;

#include <cstdint>

#include <vector>



using ValueType = std::uint_fast16_t;


static const struct Solution {

    static const std::vector<std::vector<int>> subsets(

            const std::vector<int>& nums

    ) {

        std::vector<std::vector<int>> subs = {{}};

        ValueType subs_len;


        for (const auto& num : nums) {

            subs_len = std::size(subs);


            for (ValueType len = 0; len < subs_len; ++len) {

                subs.emplace_back(subs[len]);

                subs.back().emplace_back(num);

            }

        }


        return subs;

    }

};

Python 还有一个combinations工具可以让它变得简单:


class Solution:

    def subsets(self, nums):

        return (tuple(j) for i in range(len(nums) + 1) for j in itertools.combinations(nums, i))



查看完整回答
反对 回复 2022-06-27
  • 2 回答
  • 0 关注
  • 88 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信