【leetcode】565. Array Nesting
You are given an integer array nums of length n where nums is a permutation of the numbers in the range [0, n - 1].
You should build a set s[k] = {nums[k], nums[nums[k]], nums[nums[nums[k]]], ... } subjected to the following rule:
- The first element in s[k] starts with the selection of the element nums[k] of index = k.
- The next element in s[k] should be nums[nums[k]], and then nums[nums[nums[k]]], and so on.
- We stop adding right before a duplicate element occurs in s[k].
Return the longest length of a set s[k].
1、暴力求解方法: 时间复杂度高了 超时了
class Solution { public: int arrayNesting(vector<int>& nums) { //先用暴力法写 这样写时间复杂度太高了 相当于o(n^2) int n=nums.size(); int len=INT_MIN; for(int i=0;i<n;++i) { unordered_set<int> res; int index=i; while(!res.count(nums[index])) { res.insert(nums[index]); index=nums[index]; } len=max(len,(int)res.size()); } return len; } };
分析:暴力法是对nums中的每一个数字 都作为起始数字开始 进行array nesting 嵌套
对于已经遍历过的数字就不需要让他作为开头进行遍历 因为其之后的检索路径已经是之前的一个子集合
同时检索的过程中 也不需要set 只需要存头数字 如果当前数字和头数字一样那么就结束 了
2、按照这两个思路 对代码进行优化 用一个dp数组进行存储
class Solution { public: int arrayNesting(vector<int>& nums) { //先用暴力法写 这样写时间复杂度太高了 相当于o(n^2) int n=nums.size(); int len=INT_MIN; unordered_set<int> dp;//用于存储哪些结点已经访问过了 for(int i=0;i<n;++i) { int index=i; if(dp.count(index)) continue; //dp.insert(index); //没有访问存储当前路径 unordered_set<int> res; while(!res.count(nums[index])) { res.insert(nums[index]); dp.insert(index); index=nums[index]; } len=max(len,(int)res.size()); } return len; } };
3、取消存储数据的 res 直接存访问的头结点
class Solution { public: int arrayNesting(vector<int>& nums) { //先用暴力法写 这样写时间复杂度太高了 相当于o(n^2) int n=nums.size(); int len=INT_MIN; unordered_set<int> dp;//用于存储哪些结点已经访问过了 for(int i=0;i<n;++i) { int index=i; if(dp.count(index)) continue; //dp.insert(index); //没有访问存储当前路径 int front=index; int tmp_len=1; while(front!=nums[index]) { //res.insert(nums[index]); dp.insert(index); index=nums[index]; tmp_len++; } len=max(len,tmp_len); } return len; } };