一道有意思的JAVA题

昨天做了一道很有意思的题,大概是说把一个数组等分,但是不是全部等分,而且要去掉等分之间的那个数。(不方便把题目说清楚啦)

然后重点是要求时间复杂度为O(n),空间复杂度最高不超过O(n)。

当时做的时候很紧急,怕交白卷,直接暴力的用多重循环来做了。主要根本没时间想,紧张起来就没思路。

后来晚上11点半,睡前冥思苦想,最后想到了一种办法,但是无法证明这个方法是不是正确的。


我的思维是这样的,如果要把一个数组N等分,那么需要去掉的的数就有N-1个。

而空间复杂度要求O(N),那么循环套循环是不可取的,但是求和的过程本身就是一个循环,如何一次循环就能求到想要的和呢?

空间复杂度也是O(N),不可能用来存放所有的和的组合可能性。

而且需要判断这个数组能不能N等分,判断不能直接判断,因为去掉的N-1的个可正可负。只能通过不满足一定的条件输出false。


比如给出测试用例:A={3,7,1,2,1,5,2,17,10,1,1,9} 如果把A四分,就是{3,7}{2,1,5,2}{10}{1,9};


我最后最后想到的方法是,设立N-1个标志位,每个标志位上对应的是应该剔除的元素,通过判断每个标志位是否两边相等,移动标志位到能够相等。

如果两个标志位相邻,则输入flase了。 

为了避免无限循环的情况,我要求第一个和最后一个标志位只能向内移动,不能回移。


下面是我的代码,边想边写的,写的乱七八糟的,也不改了,表达的就是上面这个思想吧。 

/**
 * 
 */
package ReadyForTest;

import java.util.*;
import java.math.*;

/** 
* * @author LilyLee
 * @date  2017年3月4日
 * @Version 
 *
 */
public class reserive {

	boolean res(int[] A){
		int len=A.length;
		int flag1=1;
		int flag2=(len+1)/2;
		int flag3=len-2;
		int sum1=0;
		int sum2=0;
		int sum3=0;
		int sum4=0;
		
		
		sum1 = sum(0, flag1 - 1, A);
		sum4 = sum(flag3 + 1, len - 1, A);
		sum2 = sum(flag1+ 1, flag2 - 1, A);
		sum3 = sum(flag2 + 1, flag3 - 1, A);	
		
		
		while(true){
			
			if(sum1==sum2&&sum1==sum3&&sum1==sum4){System.out.println("true"); return true;}
			
			if((flag1+1==flag2)||(flag2+1==flag3)){System.out.println("false"); return false;}
			int aa=Math.abs(sum2-sum1);
			int bb=Math.abs(sum3-sum2);
			int cc=Math.abs(sum4-sum3);
				
			int max=(aa>bb)?aa:bb;
			max=(max>cc)?max:cc;
			
			if(aa==max){
				
				if(sum1<sum2){
					sum1+=A[flag1];
					flag1=flag1+1;
					sum2-=A[flag1];
					
				}				
			}
			
			if(bb==max){
				
				if(sum2<sum3){
					
					sum2+=A[flag2];
					flag2+=1;
					sum3-=A[flag2];
					
				}
				else {
					
					sum3+=A[flag2];
					flag2-=1;
					sum2-=A[flag2];
					
					
				}
			}
			if(cc==max){
				
				if(sum3>sum4){
					sum4+=A[flag3];					
					flag3-=1;
					sum3-=A[flag3];
					
					}	
				
					
					
				}
			
			
			
			
		}
		
	}
	
	public static void main(String args[]){
		
		int []A={2,5,1,1,1,1,4,1,7,3,7};
		//int []A={10,2,11,13,1,1,1,25,1};
		//int []A={10,2,11,13,1,1,1,1,1};
		//int [] A={3,7,1,2,1,5,2,18,10,1,1,9} ;
		//int [] A={9,1,1,10,18,2,5,2,1,1,7,3} ;
		reserive se=new reserive();
		se.res(A);
			
		
		
	}
	public static int sum(int i, int j, int[] arr) {
		int sum = 0;
		for (int k = i; k <= j; k++) {
			sum += arr[k];
		}
		return sum;
	}

}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值