力扣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++在内存管理和对象模型方面的根本区别。

相关推荐
.生产的驴7 分钟前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
猿周LV14 分钟前
JMeter 安装及使用 [软件测试工具]
java·测试工具·jmeter·单元测试·压力测试
知来者逆16 分钟前
计算机视觉——速度与精度的完美结合的实时目标检测算法RF-DETR详解
图像处理·人工智能·深度学习·算法·目标检测·计算机视觉·rf-detr
晨集16 分钟前
Uni-App 多端电子合同开源项目介绍
java·spring boot·uni-app·电子合同
时间之城19 分钟前
笔记:记一次使用EasyExcel重写convertToExcelData方法无法读取@ExcelDictFormat注解的问题(已解决)
java·spring boot·笔记·spring·excel
阿让啊21 分钟前
C语言中操作字节的某一位
c语言·开发语言·数据结构·单片机·算法
এ᭄画画的北北21 分钟前
力扣-160.相交链表
算法·leetcode·链表
椰羊~王小美26 分钟前
LeetCode -- Flora -- edit 2025-04-25
java·开发语言
凯酱33 分钟前
MyBatis-Plus分页插件的使用
java·tomcat·mybatis
程序员总部44 分钟前
如何在IDEA中高效使用Test注解进行单元测试?
java·单元测试·intellij-idea