leetcode.565.数组嵌套

🔞565.数组嵌套

在这里插入图片描述

核心:
本题可以把每个元素看作图上一个点,每个点都有一条出度边一条入度边

笔者认为使用标记法来解决这道题是一个不错的办法,使用max函数不断更新Max值,最后返回答案即可

但这种情况当时让笔者开始怀疑:到底是否可以用标记法呢?

🤷‍♂️笔者在做这道题时被下图这种情况迷惑了一段时间

在这里插入图片描述

事实上这个题是完全可以使用标记法的,如图所示,元素1入度加出度总共为3,与入度+出度=2相违背。


由此我们得出结论:

1. 每个结点都有一个出度边和一个入度边
2. 将数组抽象为图后,图中 若干节点 一定可以组成若干个 独立的环
3. 结合1和2不难将问题转化为:查找这若干个环里的最大长度。

下面提供两种代码思路进行解题

深度优先算法如果难以理解,可以参考第一种方式 (两者的核心是一样的)


👊暴力遍历法+标记位置:

class Solution {
public:
    int arrayNesting(vector<int>& nums) {
        int len = nums.size();
        vector<int> exits(len, 0);  // 设置访问数组
        int cur,cnt = 0;
        int Max = 0;
        for(int i = 0; i < len; ++i) {  // 看似双层循环,实际上过程已经被简化
            if(exits[i] == 1) {  // 如果已经被访问,跳过这次循环
                continue;
            }
            int cur = i; // 设置当前游标
            while(!exits[cur]) {  // 查看是否已被访问
                ++cnt;
                exits[cur] = 1;  // 设置已访问状态
                cur = nums[cur]; // 更新cur
            }
            Max = max(Max, cnt);
            cnt = 0;
        }
        return Max;
    }
};

🤦‍♀️DFS深度优先搜索:

// DFS 采用涂色法进行标记
// 代码来自 英雄哪里出来
class Solution {
    int Max, Cnt;
    int hash[200010];

    void dfs(vector <int>& nums, int u, int color) {
        if(hash[u] != -1) {  // 该点已经被访问
            return ; // 如果程序执行到这里,相当于一个回路已经走完了,回到了初始节点
        }
        hash[u] = color;
        ++Cnt;
        dfs(nums, nums[u], color);
    }    

public:
    int arrayNesting(vector<int>& nums) {   
        int i;  
        int n = nums.size();    
        int color = 0;  
        Max = 0;    
        memset(hash, -1, sizeof(hash)); 
        for(i = 0; i < n; ++i) {
            // 已经访问过的点如果再访问,一定有Cnt <= Max
            if(-1 == hash[i]) {   // 注意,已经访问过的数组不需要再访问了,如果没有这句话
                // 复杂度将上升为O(n^2)
                Cnt = 0;    
                dfs(nums, i, ++color);  
                Max = max(Max, Cnt);    
            }   
        }    
        return Max; 
    }   
}; 

DFS代码参考:
部分内容来自于 英雄哪里出来
一位非常优秀的程序员!B站指路:英雄哪里出来

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值