力扣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 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2342 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
pianmian12 小时前
python数据结构基础(7)
数据结构·算法
闲晨2 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
测开小菜鸟3 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
好奇龙猫4 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
P.H. Infinity4 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天4 小时前
java的threadlocal为何内存泄漏
java
sp_fyf_20244 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
caridle5 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express