打卡第三天:路径交叉


题目描述

给你一个整数数组 distance 。
从 X-Y 平面上的点 (0,0) 开始,先向北移动 distance[0] 米,然后向西移动 distance[1] 米,向南移动 distance[2] 米,向东移动 distance[3] 米,持续移动。也就是说,每次移动后你的方位会发生逆时针变化。
判断你所经过的路径是否相交。如果相交,返回 true ;否则,返回 false 。

提示:
1 <= distance.length <= 105
1 <= distance[i] <= 105


找出所有路径交叉的情况(归纳法)

当 i 小于等于3的时候,肯定不会交叉,故从 i 为4开始讨论:

1. 第一种交叉情况

第一种交叉情况

if( (distance[i]>=distance[i-2]) && (distance[i-1]<=distance[i-3]) ) 
	return true;

2. 第二种交叉情况

第二种交叉情况

if( (i>=4) && (distance[i-1]==distance[i-3]) && (distance[i]+distance[i-4]>=distance[i-2]) )
	return true;

3. 第三种交叉情况

第三种交叉情况

if( (i>=5) 
		&& (distance[i]+distance[i-4]>=distance[i-2]) 
		&& (distance[i-1]+distance[i-5]>=distance[i-3]) 
		&& (distance[i-2]>distance[i-4]) 
		&& (distance[i-3]>distance[i-1]))
	return true;

4. 完整代码如下

public class Practice03_3 {
	public boolean isSelfCrossing(int[] distance) {
        int n = distance.length;
        
        if(n < 4)
        	return false;
        
        for(int i=3;i<n;i++){
        	if( (distance[i]>=distance[i-2]) && (distance[i-1]<=distance[i-3]) ) 
        		return true;
        	if( (i>=4) && (distance[i-1]==distance[i-3]) && (distance[i]+distance[i-4]>=distance[i-2]) )
        		return true;
        	if( (i>=5) && 
        			(distance[i]+distance[i-4]>=distance[i-2]) && 
        			(distance[i-1]+distance[i-5]>=distance[i-3]) && 
        			(distance[i-2]>distance[i-4]) && 
        			(distance[i-3]>distance[i-1]))
        		return true;
        }
        return false;
    }
	
}

图的邻接矩阵存储路线(耗内存)

1.思路

建立一个二维数组,初始化为0,将路线的坐标与二维数组的横坐标和纵坐标联系起来,走过的位置记为1。

2.完整代码如下

public class Practice03 {
	public boolean isSelfCrossing(int[] distance) {
		int N = 1000;
		int route[][] = new int[N][N];
		for(int i=0;i<N;i++)
			for(int j=0;j<N;j++)
				route[i][j]=0;
		
		int row = N/2-1, col = N/2-1;
		route[row][col]=1;
		for(int i = 0;i<distance.length;i++){
			if((i+1)%4 == 1){ // 向上走,col+
				int len = distance[i];
				for(int j=0;j<len;j++){
					col++;
					if(route[row][col]==1)return true;
					route[row][col]=1;
				}
			}else if((i+1)%4 == 2){ // 向左走,row-
				int len = distance[i];
				for(int j=0;j<len;j++){
					row--;
					if(route[row][col]==1)return true;
					route[row][col]=1;
				}
			}else if((i+1)%4 == 3){ // 向下走,col-
				int len = distance[i];
				for(int j=0;j<len;j++){
					col--;
					if(route[row][col]==1)return true;
					route[row][col]=1;
				}
			}else{ // 向右走,row+
				int len = distance[i];
				for(int j=0;j<len;j++){
					row++;
					if(route[row][col]==1)return true;
					route[row][col]=1;
				}
			}
		}
		return false;
    }
	
}


用集合存储坐标(耗时间)

1.完整代码如下

用一个集合把走过的坐标转为字符串存储起来,每走一步,就与集合中的元素匹配。

2.完整代码如下

import java.util.ArrayList;
import java.util.List;

public class Practice03_2 {
	public boolean isSelfCrossing(int[] distance) {
		int N = 200000;
		List<String> route=new ArrayList<String>();
		
		int row = N/2-1, col = N/2-1;
		String r_c = row+""+col;
		route.add(r_c);
		for(int i = 0;i<distance.length;i++){
			if((i+1)%4 == 1){ // 向上走,col+
				int len = distance[i];
				for(int j=0;j<len;j++){
					col++;
					String temp = row+""+col;
					if(exist(route,temp))return true;
					route.add(temp);
				}
			}else if((i+1)%4 == 2){ // 向左走,row-
				int len = distance[i];
				for(int j=0;j<len;j++){
					row--;
					String temp = row+""+col;
					if(exist(route,temp))return true;
					route.add(temp);
				}
			}else if((i+1)%4 == 3){ // 向下走,col-
				int len = distance[i];
				for(int j=0;j<len;j++){
					col--;
					String temp = row+""+col;
					if(exist(route,temp))return true;
					route.add(temp);
				}
			}else{ // 向右走,row+
				int len = distance[i];
				for(int j=0;j<len;j++){
					row++;
					String temp = row+""+col;
					if(exist(route,temp))return true;
					route.add(temp);
				}
			}
		}
		return false;
    }
	
	public boolean exist(List<String> list,String s){
		for(String str:list){
			if(s.equals(str))return true;
		}
		return false;
	}
	
}

总结

第一种方法时空复杂度最好。

其余的下次更吧~~~

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值