如果题目没看懂,没看懂就对了,因为题目并不完整,下面是完整题目。


QQ截图20201014120038.jpg


假设输入的n个数字存储在 nums[]中,那么nums[i]表示第i个小朋友崇拜的是 nums[i]。

QQ截图20201014121255.jpg

这题是找出最大的那个圈中小朋友的个数,从这个图可以看出共有三个圈,其中从2开始到2结束的圈最大。

既然第i个小朋友的下一个小朋友是nums[i] ,

那么就根据i得到nums[i],根据nums[i]得到nums[i]崇拜的小朋友,

next= nums[i] 下一个小朋友

这里使用dp[]存储小朋友个数,dp[next]=dp[i]+1;

直到遇到一个已经判断过的小朋友,也就是dp[i]!=0时退出循环。


两种写法,思路相同

循环法的耗时更短,因为使用set记录已经走过的点,去除很多重复的运算。


循环法,搜索法

1,循环法,

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Main {

	/**
	 * @param args
	 */
	public static  Set<Integer> vis=new HashSet<Integer>();//记录已经走过的点
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
        int n = sc.nextInt();
        int[] nums = new int[n+1];
        for (int i = 1; i <=n; i++) {
            nums[i] = sc.nextInt();
        }
       
        int max = 0;
        for (int i = 1; i <=n; i++) {
			int dp[]=new int[n+1];//当前 到达第i个小朋友的步数
			if (vis.contains(i)) {//不用找了
				continue;
			}
			max=Math.max(check(nums, dp, i), max);
		}
        System.out.println(max);
        
    }
	
	public static int check(int nums[],int dp[],int step) {
		vis.add(step);//走过step点
		dp[step]=1;
		while (dp[nums[step]]==0) {//没走过
			int next=nums[step];
			dp[next]=dp[step]+1;
			step=next;
			vis.add(step);//走过step点
		}
		return dp[step]-dp[nums[step]]+1;
	}



	
}

搜索

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
        int n = sc.nextInt();
        int[] nums = new int[n+1];
        for (int i = 1; i <=n; i++) {
            nums[i] = sc.nextInt();
        }
       
        int max = 0;
        for (int i = 1; i <=n; i++) {
			int dp[]=new int[n+1];//当前 到达第i个小朋友的步数
			dp[i]=1;
			max=Math.max(dfs(nums, dp, i), max);
		}
        System.out.println(max);
        
    }
	
	public static int dfs(int nums[],int dp[],int step) {
		int next=nums[step];//下一个点
		if (next==step) {
			return 0;
		}
		if (dp[next]!=0) {
			return dp[step]-dp[next]+1;//得到循环的大小
		}else {
			dp[next]=dp[step]+1;
			int _ans= dfs(nums, dp, next);
			return _ans;
		}
	}



	
}



搜索2,

将已经得到的答案存储起来,下一次直接可以直接使用。优化速度。

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Main {

	/**
	 * @param args
	 */
	public static int tAns[];//将已知的答案记录下来
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
        int n = sc.nextInt();
        int[] nums = new int[n+1];
        tAns=new int[n+1];
        for (int i = 1; i <=n; i++) {
            nums[i] = sc.nextInt();
        }
       
        int max = 0;
        for (int i = 1; i <=n; i++) {
			int dp[]=new int[n+1];//当前 到达第i个小朋友的步数
			dp[i]=1;
			if (tAns[i]!=0) {
				max=Math.max(tAns[i], max);
			}else {
				max=Math.max(dfs(nums, dp, i), max);
			}
			
		}
        System.out.println(max);
        
    }
	
	
	public static int dfs(int nums[],int dp[],int step) {
		int next=nums[step];//下一个点
		if (next==step) {
			return 0;
		}
		if (tAns[step]!=0) {//返回已知的答案
			return tAns[step];
		}
		if (dp[next]!=0) {
			return tAns[step]=dp[step]-dp[next]+1;//得到循环的大小
		}else {
			dp[next]=dp[step]+1;
			int _ans= dfs(nums, dp, next);
			return _ans;
		}
	}



	
}


点赞(0)
 

0.0分

2 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 2 条评论

一个人的巴黎 3年前 回复TA
第一种方法,为什么走没走过用两个数组dp[]和vis[],而不能只用一个呢?
龚秋志 4年前 回复TA
不愧是你