zoukankan      html  css  js  c++  java
  • 一道面试题的解答_骑士获得金币问题

    这道题是今天晚上在c++交流群和一位水友给出的问题,有些同学试着解答了下;问题阐述如下:

    题目文字略去,看图即可。


    其中@jevon 的解答如下:

    也没有帮他验证;但是基本思路就是:

    遍历每一天,用一个 index 值来记录当天的索引,当出现次数 cout 达到索引值时,索引值++;

    我于是帮他用java写一个就是这个意思;我的vs出问题了,所以用的java;

    public class Demo33 {
    	public static void main(String[] args) {
    		for(int i=1;i<=20;i++){
    			setMC(i);
    		}
    	}
    	public static int setMC(int day){
    		int sum = 1;
    		int cout = 1;
    		int index = 1;
    		String s = "1";
    		for(int i=1;i<day;i++){
    			if(cout < index-1){
    				cout++;
    			}else{
    				cout = 0;
    				index++;
    			}
    			sum += index;
    			
    			if(i != day-1){
    				s = s + "+" + index;
    			}else{
    				s = s + "+" +index + "=" + sum  ;
    			}
    		}
    		System.out.println(s);
    		return sum;
    	}
    }
    但是经过我的思考,一道程序题不是为了考察编写程序而单一的出现,所以一定是有优化的方法

    所以经过我的思考,发现索引值满足;索引值为a;

    等差数列求和 a(a-1)/2 <= day < a(a+1)/2;所以可以计算出完整的a;同时得到剩下的p个(a+1)项

    例如 1+2+2+3+3+3+4+4;这里面a = 3;p = 2;凑成完全的1+2^2+3^2+3^2;的索引正好是3;余下两个p (index) = a+1的残项;

    而输入的结果 result = 1^2 + 2^2 + ... a^2 + (a+1) * p = a(a+1)(2a+1)/6 + p(a+1);

    所以编写程序如下:

    import java.util.Scanner;
    
    public class Demo {
    	public static void main(String[] args) {
    		int day = new Scanner(System.in).nextInt();
    		int a = setCout_n(day);//a就是能凑成完整的1+2^2+3^2+...+a^2 + (a+1)*p;
    		int p = day - (int)(a*(a+1)/2);
    		int result = (a*(a+1)*(2*a+1)/6) + (a+1)*p;
    		System.out.println(result);
    	}
    	
    	public static int setCout_n(int day){
    		int n = (int)(Math.sqrt(2*day + 0.5)+0.25);
    		while(day < (int)((n*n - n)/2 + 0.5)){
    			n++;
    		} 
    		return n-1;
    	}
    }
    
    要是为了看到完整的验算过程;补充一个printRR函数,方便观看1-100完整的生成过程。

    下面是验算的代码块,和上面的函数相同,只是加了一些控制台输出。

    public class Demo {
    	public static void main(String[] args) {
    		for (int i=0;i<100;i++){
    			demo(i);
    		}
    	}
    
    	public static void demo(int day) {
    		int a = setCout_n(day);//a就是能凑成完整的1+2^2+3^2+...+a^2 + (a+1)*p;
    		System.out.println("输入天数" + day);
    		int p = day - (int)(a*(a+1)/2);
    		System.out.println("完全数a = "+ a +", 余下来的p项,p = "+p);
    		int result = (a*(a+1)*(2*a+1)/6) + (a+1)*p;
    		System.out.println(result);
    		printRR(a, p);
    	}
    	
    	public static int setCout_n(int day){
    		int n = (int)(Math.sqrt(2*day + 0.5) + 0.25);
    		while(day < (int)((n*n - n)/2 + 0.5)){
    			n++;
    		} 
    		return n-1;
    	}
    	public static void printRR(int a,int p){
    		String s ="[";
    		int sum = 0;
    		for(int i=1;i<=a;i++){
    			s = s+ "(";
    			for (int j=0;j<i;j++){
    				if(j==0){
    					s = s + i;sum+=i;
    				}else{
    					s = s + "+" + i;sum+=i;
    				}
    			}
    			if(i==a){
    				s = s+")";
    				}else{
    					s =s + ")+";}
    		}
    		if(p>0){
    			s = s +"+(";
    			for (int j = 0; j< p;j++){
    				if(j==0){
    					s = s + (a+1);
    					sum+=(a+1);
    				}else{
    					s = s + "+" + (a+1);
    					sum+=(a+1);
    				}
    			}
    			s = s+")";
    		}
    		s = s + "] = "+ sum;
    		System.out.println(s);
    	}
    }
    
    结论:这个题要是用数学知识直接解答复杂度大大降低,忽略系统运算中sqrt的复杂度;我们可以得到我的方法时间复杂度大约是O(lg(n));而他的方法是O(n).

  • 相关阅读:
    Wannafly挑战赛29-A/B
    hdu-4819-线段树套线段树
    CF-877E-线段树+哈希
    CF-413E-线段树
    CF-787D-线段树建图+最短路
    CF-339D-线段树
    2017.4.26 慕课网--Java 高并发秒杀API配置文件(持续更新)
    2017.4.26 慕课网--Java 高并发秒杀API(一)
    2017.4.19 慕课网-通过自动回复机器人学习mybatis
    2017.4.18 linux中执行某文件提示权限不够
  • 原文地址:https://www.cnblogs.com/actanble/p/6713445.html
Copyright © 2011-2022 走看看