615 - Course Schedule

2017.9.11

刚开始想的是,建立parent 和 children的树,如果有既是children 又是parent的节点,那么就返回false。

这种方法没有超时,但是超出了空间限制。


后来学习到采用拓扑排序的办法。关于图的思路写在了代码的注释里边。

在细节的处理方面有不同的方法。一个是最后的最后统一判断是不是还有入度不为0的点。这样会超时。

后来是在找入度为0的点的时候就进行判断,然而还是会超时。

后来又优化了许多地方。但是总是超时,我也没办法,实在是不知道为啥了。就先这样吧。


再再后来,我知道了,是找到一个入度为0得点之后,这个点的入度应该改变为-1,不然会重复选取。

终于找到了自己错误的地方,好开心。


最初的超时代码

public static class myCourse{
		HashSet<Integer> parent;
		HashSet<Integer> children;
		public myCourse(){
			parent = new HashSet<Integer>();
			children = new HashSet<Integer>();
		}
	}
	public static boolean canFinish1(int numCourses, int[][] prerequisites) {
        // Write your code here
		myCourse []arr = new myCourse[numCourses];
		for(int []x : prerequisites){
			if(arr[x[0]] == null){
				arr[x[0]] = new myCourse();
			}
			if(!arr[x[0]].children.contains(arr[x[1]])){
				arr[x[0]].children.add(x[1]);
			}
			if(arr[x[1]] == null){
				arr[x[1]] = new myCourse();
			}
			if(!arr[x[1]].parent.contains(arr[x[0]])){
				arr[x[1]].parent.add(x[0]);
			}
			for(int tmp : arr[x[1]].children){
				if(tmp == x[0]){
					return false;
				}
				if(!arr[x[0]].children.contains(tmp)){
					arr[x[0]].children.add(tmp);
				}
			}
			for(int tmp : arr[x[0]].parent){
				if(tmp == x[1]){
					return false;
				}
				if(!arr[x[1]].parent.contains(tmp)){
					arr[x[1]].parent.add(tmp);
				}
			}
		}
		return true;
				
    }

后来的超时代码,就是最后统一检查入度的方法。

public static boolean canFinish2(int numCourses, int[][] prerequisites){
		// 首先是要构建图。
		ArrayList<HashSet<Integer>> list = new ArrayList<HashSet<Integer>>();
		// 先建立头结点。
		for(int i = 0; i < numCourses; i++){
			list.add(new HashSet<Integer>());
		}
		//建立所有的后序链表。     // inDegree计算所有的节点的入度。
		int []inDegree = new int[numCourses];
		for(int []x : prerequisites){
			if(!list.get(x[0]).contains(x[1])){
				list.get(x[0]).add(x[1]);
				inDegree[x[1]] ++;
			}
		}
	//找到一个入度为0的节点,开始遍历。
		for(int j = 0; j < numCourses; j++){
		    int i = 0;
			for(i = 0; i < inDegree.length;i++){
				//在这里找到了一个入度为0的点。
				if(inDegree[i] == 0 && !list.get(i).isEmpty()){
					Iterator ite = list.get(i).iterator();
					while(ite.hasNext()){
						int tmp = (int)ite.next();
						inDegree[tmp]--;
						ite.remove();
					}
					break;
				}
				
			}
		}
		for(int i = 0; i< inDegree.length;i++){
			if(inDegree[i] != 0){
				return false;
			}
		}
		return true;
		
	}

最后最后,把能简化的都简化了,然而还是超时的代码。

后来稍稍修改一下。就AC了。

public static boolean canFinish(int numCourses, int[][] prerequisites){
		// 首先是要构建图。
		ArrayList<HashSet<Integer>> list = new ArrayList<HashSet<Integer>>();
		// 先建立头结点。
		for(int i = 0; i < numCourses; i++){
			list.add(new HashSet<Integer>());
		}
		//建立所有的后序链表。 
		
		for(int []x : prerequisites){
			list.get(x[0]).add(x[1]);	
		}
	    // inDegree计算所有的节点的入度。
		int []inDegree = new int[numCourses];
		for(HashSet set : list){
			Iterator ite = set.iterator();
			while(ite.hasNext()){
				inDegree[(int)ite.next()]++;
			}
		}
		//找到一个入度为0的节点,开始遍历。
		for(int j = 0; j < numCourses; j++){
			int i = 0;
			for(i = 0; i< numCourses;i++){
				//在这里找到了一个入度为0的点。
				if(inDegree[i] == 0){
					break;
				}
			}
			if(i == numCourses){
				return false;
			}
                        //这里这里就是在这里啊,这个我忽视了啊啊啊啊。
                        inDegree[i] = -1;
  Iterator ite = list.get(i).iterator();while(ite.hasNext()){inDegree[(int)ite.next()]--;}}return true;}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值