2013.9.22 阿里校招 筆試題之 在黑板上寫下50個數字,1至50

2013年9月22日 阿里巴巴校招 算法、研發 題之(僅供學習討論)

在黑板上寫下50個數字:1至50,在接下來的49輪操作中,每次做如下操作,選取兩個黑板上的數字a和b,擦去,在黑板上寫|b-a|,請問最後一次動作之後剩下數字可能是什麼?爲什麼?(不用寫代碼,不寫原因不得分)。

 

1至n的數字,剩餘的數字肯定爲0至n的數字,假如剩下k,則可以這樣認爲,1至n的數字中除k外的數字全部抵消了。當任意選擇a、b時,假如a較小,這些數字的總和將減少2a,即使是b,最後消爲0時,也將減去2b,最後全部消失。所以這些數字的和一定是偶數2*m,m是這些數字中(k除外)的數字組合,如存在這個組合,那麼就可以。

 

分析及就到此爲止了,以下是我Java實現的代碼,

package algorithm;

public class Remove2s1 {
	
	public void WhatLeft(int n){
		int total = n*(n+1)/2;
		int beginNum;
		if(total%2 == 0){
			beginNum = 0;
		}else{
			beginNum = 1;
		}
		System.out.println("These numbers maybe left: ");
		for(;beginNum<=n;beginNum+=2){
			if(MaybeLeft(n,beginNum,total)){
				System.out.print(beginNum+", ");
			}
		}
	}
	
	public boolean MaybeLeft(int n, int num, int total){
		int leftTotal = (total-num)/2;
		int[] numArr = new int[n+1];
		for(int i=0; i<=n; i++){
			numArr[i] = i;
		}
		numArr[num] = 0; 
		int sum = 0;
		int index = n;
		while(index>0){
			if(sum+numArr[index] == leftTotal){
				return true;
			}else if(sum+numArr[index] < leftTotal){
				sum += numArr[index];
			}
			index --;
		}
		
		return false;
	}
	
	public boolean MaybeLeft(int n, int num){
		int total = n*(n+1)/2;
		if(MaybeLeft(n,num,total)){
			System.out.println("OK!");
			
			printOrder(n,num,total);
			
			return true;
		}else{
			System.out.println("No!");
			return false;
		}
	}
	
	public void printOrder(int n, int num, int total){
		int leftTotal = (total-num)/2;
		int[] numArr = new int[n+1];
		for(int i=0; i<=n; i++){
			numArr[i] = i;
		}
		numArr[num] = 0; 
		int sum = 0;
		int index = n;
		System.out.println("Select there numbers:");
		while(index>0){
			if(sum+numArr[index] == leftTotal){
				System.out.print(numArr[index]);
				break;
			}else if(sum+numArr[index] < leftTotal){
				sum += numArr[index];
				if(numArr[index] != 0){
					System.out.print(numArr[index]+", ");
				}
				
			}
			index --;
		}
	}
	
	public static void main(String args[]){
		Remove2s1 rem = new Remove2s1();
		rem.WhatLeft(50);
		rem.MaybeLeft(50,9);
	}
}

運行結果就是1至50,可能剩餘的數字

輸出結果爲:

These numbers maybe left: 
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, OK!
Select there numbers:
50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 24

就是1到50之間的奇數都有可能。

或單獨查看某個數字是否能留下,一種可能是擦出順序是,從輸出的數字中,依次,從剩餘的其他數字中找數字,將該數字抵消掉,直到爲0.

例如,n=10,

Remove2s1 rem = new Remove2s1();
		rem.WhatLeft(10);
		rem.MaybeLeft(10,5);

輸出:

These numbers maybe left: 
1, 3, 5, 7, 9, OK!
Select there numbers:
10, 9, 6

要剩餘5,可以這樣:

1到10: 1、2、3、4、5、6、7、8、9、10

5要剩餘,先去掉: 1、2、3、4、6、7、8、9、10

先選10,從1、2、3、4、7、8中選兩個數消除掉,就8和2吧,剩下:1、3、4、6、7、9

再選9,從1、3、4、7中,選數字7、1吧,剩餘1、3、4、6,

最後選6,將剩餘1、3、4,想辦法抵消掉,比如6-4=2、3-2=1、1-1=0,到此爲止。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章