關於深淺拷貝的一個小坑

關於深淺拷貝的一個小坑


前言

從 c++ 轉到 java,對於 java 的基礎一直不好。今天想刷幾個題鞏固一下基礎,於是開心的刷起了 leetcode …
果然,不一會兒就掉坑裏了…

心路歷程

題目到是不難,就求給定集合的子集,二進制枚舉和深搜都能做。

題目鏈接:https://leetcode.com/problems/subsets/

啪啪啪敲完,完全是 c++ 風格 …
怎麼看都是對的,結果是所有子集都長一個模樣…
搞了半天,問題出在了淺拷貝上:

/*
tmp 是 List<Integer>,保存着當前的子集
ans 是 List< List<Integer> >,所有子集的集合
要把 tmp 傳進去的時候,直接傳引用的話,
會導致 ans 保存的引用全是一樣的,所以必須深拷貝一個新的對象。
*/

ans.add(tmp); //淺拷貝傳入引用出錯。
ans.add(new ArrayList<Integer>(tmp));   //深拷貝,正確


題解

public class Solution {

    private List<List<Integer>> dfs(int dep, int[] a, List<Integer> tmp, List<List<Integer>> ans){
        if(dep == a.length){
            //ans.add(tmp); //淺拷貝傳入引用出錯。
            ans.add(new ArrayList<Integer>(tmp));   //深拷貝
        }else{
            dfs(dep+1, a, tmp, ans);
            tmp.add(a[dep]);
            dfs(dep+1, a, tmp, ans);
            tmp.remove(tmp.size()-1);
        }
        return ans;
    }

    public List<List<Integer>> subsets(int[] nums) {
        Arrays.sort(nums);
        return dfs(0, nums, new ArrayList<Integer>(), new ArrayList<List<Integer>>());
    }
}


總結

java 的 ArrayList 和 c++ 的 vector 還是有區別的。
ArrayList 的 add 是淺拷貝,只保存了對象的引用。
vector 的 push_back 是深拷貝,傳入的時候 new 了一個新的對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章