算法學習【1】三個空汽水瓶可以換一瓶汽水

       開始在牛客網上刷題,遇到的第一題是“換汽水”問題:

       有這樣一道智力題:“某商店規定:三個空汽水瓶可以換一瓶汽水。小張手上有十個空汽水瓶,她最多可以換多少瓶汽水喝?”答案是5瓶,方法如下:先用9個空瓶子換3瓶汽水,喝掉3瓶滿的,喝完以後4個空瓶子,用3個再換一瓶,喝掉這瓶滿的,這時候剩2個空瓶子。然後你讓老闆先借給你一瓶汽水,喝掉這瓶滿的,喝完以後用3個空瓶子換一瓶滿的還給老闆。如果小張手上有n個空汽水瓶,最多可以換多少瓶汽水喝?


       本文只討論JAVA語言解決該問題的程序。

       三個空汽水瓶可以換一瓶汽水,但是又產生了一個空汽水瓶。兩個空汽水瓶可以借一瓶換一瓶汽水然後將產生的一個空汽水瓶還回,等於說兩個空汽水瓶可以換一瓶汽水,並且不產生空汽水瓶

       因此,可以得出空汽水瓶數num1與喝到的飲料數num2的關係:

num1=奇數,num2=(num1-1)/2,手裏剩餘1個空汽水瓶

num1=偶數,num2=num1/2,    手裏剩餘0個空汽水瓶

       也可以認爲,將最開始手裏的空汽水瓶數分成2個1組,每組換一瓶汽水,最後剩餘0或1個空汽水瓶。


       由於機試時間較短,一般做法是寫出幾組數據,直接找出規律編程。以題目給出的輸入例子爲例:

       初始:    num1=3,num2=0;

       換一次:num1/3=1,num1=num1/3+num1%3=1,num2=num2+num1/3=0+1=1;

       初始:    num1=10,num2=0;

       換一次:num1/3=3,num1=num1/3+num1%3=4,num2=num2+num1/3=0+3=3;

       換二次:num1/3=1,num1=num1/3+num1%3=2,num2=num2+num1/3=3+1=4;

       換三次:num1/3=0,num1=num1/3+num1%3=2,num2=num2+num1/3=4+1=5;

       從10->4->1的過程,可以得出其實是一個遞歸的過程,遞歸公式爲:a(n+1)=a(n)/3+a(n)%3,終止條件是手裏的空汽水瓶數num1小於3,num1=1直接返回,num1=2時num2++返回。程序如下:

import java.util.Scanner
public class MyCode3{
	static int num2=0;//喝道的飲料數

	public static void main(String[] args){
		int[] num1 = new int[10];//空瓶子數
		int count = 0, temp;
		Scanner sc = new Scanner(System.in);
		while(count<10){
			temp = sc.nextInt();
			if(temp==0)	break;
			num1[count] = temp;
			count++;
		}

		for(int i=0;i<count;i++){
			num2 = 0;
			fun(num1[i]);
			System.out.println(num2);
		}
	}

	public static void fun(int n){
		if(n==1){
			return;
		}if(n==2){
			num2++;
			return;
		}else if(n>=3){
			num2 = num2+n/3;
			fun(n/3+n%3);
		}
	}
}

       有時候機試較緊張,一時無法找出遞歸規律,或者遞歸函數編程不熟悉,則可以考慮用循環。程序模擬換水瓶過程,從一堆空汽水瓶裏一個一個往外拿,積累到三個就換一次,最後空汽水瓶剩2個也換一個然後結束,空汽水瓶剩0或1個也結束

import java.util.Scanner;
public class MyCode4{
	public static void main(String[] args){
		int[] num1=new int[10];
		int count=0, temp;
		Scanner sc = new Scanner(System.in);

		while(count<10){
			temp = sc.nextInt();
			if(temp==0)	break;
			num1[count] = temp;
			count++;
		}

		int num2, n;
		for(int i=0;i<count;i++){
			num2=0;
			n=0;

			while(num1[i]>=2){
				if(num1[i]==2){
					num2++;
					num1[i]=0;
				}else if(n==3){
					num2++;
					num1[i]=num1[i]-3+1;
					n=0;
				}
				n++;
			}

			System.out.println(num2);
		}
	}
}

       

       可見,這道題的核心是遞歸,因此把遞歸最經典的斐波那契數列JAVA程序拿出來。

       函數名:int getFibo(int n)

       輸入:數組序號n,範圍1,2,3...

       輸出:getFibo(1)=getFibo(2)=1,getFibo(n+2)=getFibo(n+1)+getFibo(n)

public class MyCode1{
	public static void main(String[] args){
		for(int i=1;i<=10;i++){
			System.out.println(getFibo(i));
		}
	}

	public static int getFibo(int n){
		if(n==1) return 1;
		else if(n==2) return 1;
		else return (getFibo(n-1)+getFibo(n-2));
	}
}



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