leetcode:565. 数组嵌套

题目来源

题目描述

在这里插入图片描述

class Solution {
public:
    int arrayNesting(vector<int>& nums) {
   
    }
};

题目解析

题意

不断地执行i=A[i],每次取出A[i],直到出现重复,显然,这会形成循环

在这里插入图片描述

  • 循环1:A[5]=6,A[6]=2,A[2]=0,A[0]=5
  • 循环2:A[4]=1,A[1]=4
  • 循环3(自循环):A[3]=3

共三组循环,可以把它们拆分开来,变成下图的样子
在这里插入图片描述
可以总结出一些性质:

  • 对每一个循环,无论从哪里进入,结果都是一样的
  • 由于不存在重复数字,也就是说不可能两个数字指向同一个地方,所以每个循环不存在交叉,因此查找过的元素一定不会被再次查找

思路

  • 根据题意模拟,顺序遍历整个数组,尝试以它为开头找到循环
    • 对我们经过的每一个元素:
      • 首先,不应再用它当开头——这会造成重复查找;
      • 其次,其他循环不会经过它----因为没有交叉
    • 也就是说,一旦经过某个元素,以后就不可能再用上它,所以可以把它抹去,可以原地地将它置为-1,或者是n等等不会出现的数。
  • 不断查找,直到回到开头,这个循环结束,size记录了循环的长度。返回最大的size即可

问题:为什么一定会在入口处成环

  • 先证明一定成环:
    • 在没有回头指向遍历过的节点时,这个结构是线性的,但是最终状态不可能是线性的,因为每个节点必然指向某个节点,也必然被某个节点所指,所以它不可能真正的有头有尾。
    • 最长的可能就是遍历完整个数组,最后返回到某个值并成环。
  • 证明必然在遍历开始处成环:
    • 关键在于没有相同元素
    • 根据上面的证明,一定成环,假如不在开头处成环,就一定返回到中间某个节点,但这必然造成重复。
    • 为什么呢?
      • 首先,在遍历时,已经有一个元素指向它了,现在又返回到它,不就有两个相同的值了吗?
      • 类似于下图的情况。所以必须返回到还没有被指向的节点,也就是遍历的开头。

在这里插入图片描述

class Solution {
public:
    // 1 <= nums.length <= 10^5
    // 0 <= nums[i] < nums.length
    int arrayNesting(vector<int>& nums) {
        int maxLen = 0;
        for (int i = 0; i < nums.size(); ++i) {
            if(nums[i] < 0){
                continue;
            }

            int currLen = 1;
            int nextIdx = nums[i]; // 获取下一个位置的下标
            nums[i] = -1;          // 当前环标记为已经使用过
            while (nextIdx != i){    // 下一个位置是否指向起始节点
                ++currLen;  //环长度++, 现在nextIdx变为currIdx
                int tmp = nums[nextIdx];// 获取下一个位置的下标
                nums[nextIdx] = -1; //
                nextIdx = tmp;
            }
            maxLen = std::max(maxLen, currLen);
        }
        return maxLen;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值