565. Array Nesting(dfs 血的教训)

22 篇文章 0 订阅
3 篇文章 0 订阅

为什么说是血的教训呢,因为明明自己想的思路与那些AC的人思路一样

而自己偏偏超时,又爆内存,觉得很奇怪,偏偏又找不出问题所在

这道题,看完题意就知道dfs的思路了,却因为很小的细节卡了我2个小时!!!!! 泪崩

先看题目:

A zero-indexed array A consisting of N different integers is given. The array contains all integers in the range [0, N - 1].

Sets S[K] for 0 <= K < N are defined as follows:

S[K] = { A[K], A[A[K]], A[A[A[K]]], ... }.

Sets S[K] are finite for each K and should NOT contain duplicates.

Write a function that given an array A consisting of N integers, return the size of the largest set S[K] for this array.

Example 1:

Input: A = [5,4,0,3,1,6,2]
Output: 4
Explanation: 
A[0] = 5, A[1] = 4, A[2] = 0, A[3] = 3, A[4] = 1, A[5] = 6, A[6] = 2.
One of the longest S[K]: S[0] = {A[0], A[5], A[6], A[2]} = {5, 6, 2, 0}

Note:

  1. N is an integer within the range [1, 20,000].
  2. The elements of A are all distinct.
  3. Each element of array A is an integer within the range [0, N-1].
题意:

给出了由N个不同整数组成的零索引数组A. 该数组包含范围[0,N - 1]中的所有整数。

设置0 <= K <N的S [K]定义如下:

S [K] = {A [K],A [A [K]],A [A [A [K]]],...}。

集合S [K]对于每个K是有限的,不应包含重复项。

写一个给定由N个整数组成的数组A的函数,返回该数组的最大集合S [K]的大小。

思路:一开始没申清题目,只想到for循环遍历数组dfs做  这样Time O(n^2)超时也绝理所当然
  然后仔细看清出题目note2和3点: Each element of array A is an integer within the range [0, N-1].
  也就是说每个数组值在0-n-1之间,并且不重复
  这样就想到了用一个标技数组,访问过的数组标记一下,不重复dfs,这样 Time 变为O(N)
  可是让我没想到的还是超时,有时还报内存。。。。。。
代码:错误代码(思想没错是Time O(n) 细节问题 大家可以看看错在哪) 有时Time Limit Exceeded 有时 Memory Limit Exceeded
class Solution {
public:
    int dfs(vector<int> nums,vector<int>& flag,int curva){
        int len = nums.size();
        if(!flag[curva]){
            flag[curva] = 1;
            int max = dfs(nums,flag,nums[curva])+1;
            return max;
        }
        return 0;
    }
    
    int arrayNesting(vector<int>& nums) {
        int len = nums.size();
        if(len==0)
            return 0;
        if(len==1)
            return 1;
        vector<int> flag(len, 0);
        int maxlen = 0;
        for(int i=0;i<len;i++){
            if(flag[i]==1)
                continue;
            int deep = dfs(nums,flag,i);
            if(maxlen<deep)
                maxlen = deep;
            if(maxlen==len)
                break;
        }
        return maxlen;
    }
};
在这2个小时内,我不停的找问题,是Time O(n)没错,看了别人的代码也是O(n) 用的不是dfs但也是dfs的思想,不停的改,还有时爆内存问题。
一直没找到问题所在,到最后只差原封不动把有个也是dfsAC的代码拿过来改,居然还是爆内存错误!!!!!
最后,到最后,除了参数与别人不一样,其它都一样的时候。。。 我才终于发现原来是我的参数 Vector<int> nums 没有用引用&
仔细一样也是哦。。算法最注重时间和空间的大小了  当时没用引用只是想着这样传参原vector nums的数值不会被修改,没有注意到如果不用引用的话,形参就会重新复制nums一遍,这样又会增加内存,而且还是dfs,深搜压栈,没压栈又会赋值nums一遍,这样若深度很大,nums数组也很大的话。内存难免会爆掉,运行看了leetcode detail 最后3个数组过不了,很大的数组. 然而为什么有时候会超时,我不大理解,可能压栈时传参每赋值nums消耗了一定的时间吧。。。
其实只要把上述代码,形参 nums 加个&就AC了
AC代码:Time O(N) Space O(n)
class Solution {
public:
    /一直报错超时 是因为我没用引用!!!!!vector<int> nums(超时)
    int dfs(vector<int> nums,vector<int>& flag,int curva){
        int len = nums.size();
        if(!flag[curva]){
            flag[curva] = 1;
            int max = dfs(nums,flag,nums[curva])+1;
            return max;
        }
        return 0;
    }
    
    int arrayNesting(vector<int>& nums) {
        int len = nums.size();
        if(len==0)
            return 0;
        if(len==1)
            return 1;
        vector<int> flag(len, 0);
        int maxlen = 0;
        for(int i=0;i<len;i++){
            if(flag[i]==1)
                continue;
            int deep = dfs(nums,flag,i);
            if(maxlen<deep)
                maxlen = deep;
            if(maxlen==len)
                break;
        }
        return maxlen;
    }
};
当时看了这道题,其实很快就想出怎么做了,只是细节问题,我没注意到, 以后要好好注意参数的传递细节了!!!!!
上述代码还可以优化下,压缩时间 Space O(1)的 ,没必要格外弄个flag数组,直接在原数组nums标记,若使用过 就标记 -1 不过这样会改变原数组的值。。。
AC代码:Time O(N) Space O(1)
class Solution {
public:
    /一直报错超时 是因为我没用引用!!!!!vector<int> nums(超时)
    int dfs(vector<int>& nums,int curva){
        int len = nums.size();
        if(nums[curva]!=-1){
            int temp = nums[curva];
            nums[curva] = -1;
            int max = dfs(nums,temp)+1;
            return max;
        }
        return 0;
    }
    
    int arrayNesting(vector<int>& nums) {
        int len = nums.size();
        if(len==0)
            return 0;
        if(len==1)
            return 1;
        int maxlen = 0;
        for(int i=0;i<len;i++){
            if(nums[i]==-1)
                continue;
            int deep = dfs(nums,i);
            if(maxlen<deep)
                maxlen = deep;
            if(maxlen==len)
                break;
        }
        return maxlen;
    }
};

总结:一定要注意传参内存问题,还有AC完之后 看看时间和空间是否还可以在压缩!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值