leetcode46引发的小思考--数组转化为ArrayList&ArrayList的底层实现

2 篇文章 0 订阅

leetcode46 全排列
这里没有题解emm,象征性地指路官方题解
这里着重回溯法的两种传参方式
a. nums用流转化为list再加入到ans当中
执着了很久想要把int [] nums转化为Arraylist< Integer >然后加入结果
发现只能用流,具体可见这个

class Solution {
    private List<List<Integer>> ans = new ArrayList<List<Integer>>();
    public List<List<Integer>> permute(int[] nums) {
        if(nums.length == 0) return ans;
        backTrack(nums,0);
        return ans;
    }
    private void backTrack(int [] nums,int i){
        if(i == nums.length - 1) {
        //转化:
            List<Integer> list = Arrays.stream(nums).boxed().collect(Collectors.toList());
            ans.add(list);
        }
        int length = nums.length;
        for(int j = i; j < length; j++){
            swap(nums,i,j);
            backTrack(nums,i+1);
            swap(nums,i,j);
        }
    }
    private void swap(int [] nums,int i , int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

b.传参数的时候直接传arraylist而不是数组

class Solution {
    private List<List<Integer>> ans = new ArrayList<List<Integer>>();
    public List<List<Integer>> permute(int[] nums) {
        if(nums.length == 0) return ans;
        List<Integer> list = new ArrayList<Integer>();
        for(int i : nums) list.add(i);
        backTrack(nums,0,list);
        return ans;
    }
    private void backTrack(int [] nums,int i,List<Integer> list){
        if(i == nums.length - 1) {
            ans.add(new ArrayList<>(list));/*!!!!!!!!!!!!!!!!!!!*/
        }
        int length = nums.length;
        for(int j = i; j < length; j++){
            Collections.swap(list, i, j);
            backTrack(nums,i+1,list);
            Collections.swap(list, i, j);
        }
    }

}

然而看看速度
用流的:
在这里插入图片描述
用array的

在这里插入图片描述
所以流还是慎用鸭


这里还有一个玄学
我第一次交的时候在上面标注感叹号的地方是这么写的:

		if(i == nums.length - 1) {
            ans.add(list);
        }

完全知道是怎么肥四的就不用往下看啦
然后发现运行结果长这样:
在这里插入图片描述
人又懵了…
明明算法没有问题的嘛
改成ans.add(new ArrayList<>(list));立马就过了

然后我又跑去康了源码
在这里插入图片描述
⬆️发现ArrayList的内部有一个Object数组用来存放数据
在这里插入图片描述
⬆️add就是把某个元素加到这个数组当中

然后就怀疑到了数组存放方式上
翻到了之前看深入理解jvm的笔记:
在这里插入图片描述
如果声明了对象数组,获得的将是对象引用的数组
还是深入理解jvm中的图:
在这里插入图片描述
数组在栈中,存放的是引用,而引用指向堆中对象的地址
所以明白啦:
再来看这个代码:

        ans.add(new ArrayList<>(list));
        ans.add(list);

它们俩的区别是:
第一个在堆中新建了一个对象,这个对象的内容和list相同,然后把这个新对象的地址加入到了ans中

在这里插入图片描述

第二个只是不断的加入了原本那一个对象的地址
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值