陈正磊


私信TA

用户名:RossTran

访问量:13630

签 名:

晨兴理荒秽,带月荷锄归。

等  级
排  名 178
经  验 6678
参赛次数 15
文章发表 34
年  龄 0
在职情况 学生
学  校 湖北生物科技职业学院
专  业

  自我简介:

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


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分

3 人评分

看不懂代码?想转换其他语言的代码? 或者想问其他问题? 试试问问AI编程助手,随时响应你的问题:

编程语言转换

万能编程问答

代码解释器

  评论区

第一种方法,为什么走没走过用两个数组dp[]和vis[],而不能只用一个呢?
2022-03-05 11:56:52
不愧是你
2020-10-14 14:23:12
  • «
  • 1
  • »