力扣46 全排列 引发对JAVA对象引用的思考

先简单说一下本题思路:

数据结构:栈

算法:递归

使用深度遍历,得到全排列。要使用一个标记数组来标记某个数在本次递归中是否被使用,然后在下次递归前要取消标记。

java 复制代码
class Solution {
    private  int[] flag;
    private List<List<Integer>> v = new ArrayList<>();
    private List<Integer> vv = new ArrayList<>();
    
    public List<List<Integer>> permute(int[] nums) {
        flag = new int[nums.length];
        dfs(nums);
        return v;
    }

    private void dfs(int [] nums){
        if(vv.size() == nums.length){
            // v.add(vv);
            v.add(new ArrayList<>(vv));
            return;
        }

        for(int i = 0; i < nums.length; i++){
            if(flag[i] == 0){
                flag[i] = 1;
                vv.add(nums[i]);
                dfs(nums); 
                vv.remove(vv.size()-1);
                flag[i] = 0;
            } 
        }
    }
}

重点看我注解的这段代码,之前用c++写程序习惯了,但是换到JAVA导致结果一直是空。仔细思考和查了下资料:

通过执行 v.add(vv);,实际上添加的是对列表 vv 的引用,而不是当前内容的快照。因为在整个 DFS 过程中 vv 不断被修改,所以在 v 中的所有条目最终都会成为同一个列表的引用------而一旦递归完成,这个列表就会是空的。

改成v.add(new ArrayList<>(vv))确保了存储在 v 中的每个排列在被添加到列表时都准确反映了当时的实际状态,而不是最后都指向同一个(最终为空的)列表 vv。

在Java中,对象(包括那些实现了List接口的对象,如ArrayList)是通过引用来操作的。将vv添加到v中时,若是直接添加vv,实际上添加的是vv这个列表的引用,而不是它此刻的内容拷贝。这意味着,随后对vv的所有修改(添加元素、删除元素等操作),都会反映在v中所保存的这个引用所指向的同一个列表对象上。

再向下引申一点,在c++中为什么直接用v.push_bcak(vv)就可以呢?

这是因为C++在这种情境下执行的是对象的复制(copy),而不是引用(或指针)的复制。对于C++的std::vector(或大多数标准容器),push_back方法会创建一个参数的副本,并将这个副本存入容器中。因此,在C++中不需要显式地从vv创建一个新的std::vector对象就可以直接使用push_back(vv),因为push_back便已自动完成了这一复制工作。

这种差异归根结底是由于Java和C++对对象和容器的操作语义不同。Java中的对象赋值通常是引用赋值,而C++中的赋值(包括容器中元素的插入)则是创建对象副本的复制操作。这也反映了Java和C++在内存管理和对象模型方面的根本区别。

相关推荐
你真是饿了2 分钟前
算法专题二:滑动窗口
算法
ccLianLian8 分钟前
数论·约数
数据结构·算法
会编程的土豆8 分钟前
【数据结构与算法】最短路径---Dijkstra 算法
数据结构·c++·算法
2401_879693879 分钟前
C++中的观察者模式实战
开发语言·c++·算法
炽烈小老头11 分钟前
【 每天学习一点算法 2026/03/24】寻找峰值
学习·算法
fff98111830 分钟前
C++与Qt图形开发
开发语言·c++·算法
计算机安禾44 分钟前
【数据结构与算法】第3篇:C语言核心机制回顾(二):动态内存管理与typedef
c语言·开发语言·数据结构·c++·算法·链表·visual studio
23.44 分钟前
【Java】char字符类型的UTF-16编码解析
java·开发语言·面试
怒放吧德德1 小时前
Spring Boot实战:InfluxDB 2.x简单教程
java·spring boot·后端
indexsunny1 小时前
互联网大厂Java面试实战:核心技术与业务场景深度解析
java·spring boot·hibernate·security·microservices·interview