??前面的話??
本篇文章帶大家認識Java方法,介紹Java方法之前我提一下函式,在數學中我相信大家一定都認識什么是函式,比如正反比例函式,二次函式,冪函式,指數函式,三角函式等等,
函式在數學上的定義:給定一個非空的數集A,對A施加對應法則f,記作f(A),得到另一數集B,也就是B=f(A).那么這個關系式就叫函式關系式,簡稱函式.
簡單來講,對于兩個變數x和y,如果每給定x的一個值,y都有唯一一個確定的值與其對應,那么我們就說y是x的函式,其中,x叫做自變數,y叫做因變數,
而對于編程而言,此函式非彼函式,就拿C語言來說,函式是一段可以重復使用的代碼,用來獨立地完成某個功能,它可以接收用戶傳遞的資料,也可以不接收,接收用戶資料的函式在定義時要指明引數,不接收用戶資料的不需要指明,根據這一點可以將函式分為有參函式和無參函式,
將代碼段封裝成函式的程序叫做函式定義,
Java中所謂的方法就是其他編程語言的“函式”,都是將一個實作單一的功能的代碼封裝,
📒博客主頁:未見花聞的博客主頁
🎉歡迎關注🔎點贊👍收藏??留言📝
📌本文由未見花聞原創,CSDN首發!
📆首發時間:🌴2021年10月23日🌴
??堅持和努力一定能換來詩與遠方!
💭參考書籍:📚《Java核心技術卷1》,📚《Java核心技術卷2》,📚《Java編程思想》
💬參考在線編程網站:🌐牛客網🌐力扣
🙏作者水平很有限,如果發現錯誤,一定要及時告知作者哦!感謝感謝!
博主的碼云gitee,平常博主寫的程式代碼都在里面,
📌導航小助手📌
- 🍨1.Java方法基本構造
- 🍦1.1Java方法是什么?
- 🍦1.2Java方法的定義
- 🍦1.3Java方法的執行程序與引數
- 🍦1.4完成判斷素數的函式
- 🍨2.Java方法的多載
- 🍨3.Java方法的遞回
- 🍦3.1斐波拉契數列
- 🍦3.2青蛙跳臺階問題
- 🍧3.2.1題目描述及思路
- 🍧3.2.2代碼演示
- 🍦3.3漢諾塔問題
- 🍧3.3.1問題描述及思路
- 🍧3.3.2代碼演示

🍨1.Java方法基本構造
🍦1.1Java方法是什么?
在許多編程語言(比如 C 和 C++)中,“函式”用于表示子程式,而在 Java 中,我們稱之為“方法”,意思是“做某件事的方式”,
Java 中的方法決定了物件可以接受哪些訊息,方法最基礎的幾個部分包括:方法名、引數、回傳值,以及方法體,
🍁使用方法有以下的優點:
- 是能夠模塊化的組織代碼(當代碼規模比較復雜的時候).
- 做到代碼被重復使用, 一份代碼可以在多個位置使用.
- 讓代碼更好理解更簡單.
- 直接呼叫現有方法開發, 不必重復造輪子.
🍁我們要帶著問題去學習,現在我給你一段判斷一個數是否是素數的代碼,讓你改造成一個方法判斷一個數是否是素數,回傳值型別要求是boolean,
public static void main(String[] args) {
// 判定一個數字是否是素數
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int a = sc.nextInt();
if (a == 2) {
System.out.println(a + "是素數!");//true
continue;
}
boolean flag = true;
if (a % 2 == 0 || a <= 1) {
System.out.println(a + "不是素數!");//false
}else {
for (int i = 2; i <= Math.sqrt(a); i++) {
if (a % i == 0) {
System.out.println(a + "不是素數!");//false
flag = false;
break;
}
}
if (flag) {
System.out.println(a + "是素數!");//true
}
}
}
}
🍦1.2Java方法的定義
ReturnType methodName( /* 引數串列 */ ) {
// 方法體
}
現在我們不討論public,private,static,我們定義方法就像main方法一樣去定義:
//定義方法
public static 方法回傳值 方法名稱([引數型別 形參 ...]){
方法體代碼;
[return 回傳值];
}
//如
public static boolean isPrime(int a) {
//方法體
}
//呼叫
回傳值變數 = 方法名稱(實參...);
boolean ret = isPrime(13);
🍁注意:
- public 和 static 兩個關鍵字在此處具有特定含義, 我們暫時不討論, 后續博文會詳細介紹.
- 方法定義時, 引數可以沒有,每個引數要指定型別.
- 方法定義時, 回傳值也可以沒有, 如果沒有回傳值, 則回傳值型別應寫成 void.
- 方法定義時的引數稱為 “形參”, 方法呼叫時的引數稱為 “實參”.
- 方法的定義必須在類之中, 代碼書寫在呼叫位置的上方或者下方均可.
- Java 中沒有 “函式宣告” 這樣的概念.
我們會進行方法的定義后,我們就能寫出判斷素數方法的外殼了!做好了外殼,就差內部的方法體了,方法體的內容就是對素數判斷實作的內容,
🍦1.3Java方法的執行程序與引數
🍁基本規則🍁
- 定義方法的時候, 不會執行方法的代碼. 只有呼叫的時候才會執行.
- 當方法被呼叫的時候, 會將實參賦值給形參.
- 引數傳遞完畢后, 就會執行到方法體代碼.
- 當方法執行完畢之后(遇到 return 陳述句), 就執行完畢, 回到方法呼叫位置繼續往下執行.
- 一個方法可以被多次呼叫.

對于基礎型別來說, 形參相當于實參的拷貝. 即 傳值呼叫,
🍁舉個栗子,在一個方法中進行兩數交換是無效的,因為交換的兩個數實際上是形參的交換,呼叫完函式后形參就被銷毀了,并且實參并沒有進行交換,如果需要交換兩數,可以采用陣列,陣列將在后續博文詳細介紹,
🍦1.4完成判斷素數的函式
前面已經介紹了方法的定義與使用,現在我們就可以完成改造,將前面給出的判斷素數代碼封裝,實作一個判斷素數的方法,
public static boolean isPrime(int a) {
//判定一個數字是否是素數方法
if (a == 2) {
return true;
}
if (a % 2 == 0 || a <= 1) {
return false;
} else {
for (int i = 2; i <= Math.sqrt(a); i++) {
if (a % i == 0) {
return false;
}
}
return true;
}
}
我們來測驗一下,使用該方法試著列印1-100內的素數,我沒記錯的話1-100間素數個數為25個!
public static void main(String[] args) {
//列印 1 - 100 之間所有的素數
int n = 100;
int cnt = 0;
for (int i = 1; i <= n ; i++) {
if (isPrime(i)) {
cnt++;
System.out.print(i + " ");
}
}
System.out.println("1-" + n + "素數有" + cnt + "個");
}

🍨2.Java方法的多載
public class testBlog {
public static int add(int a, int b) {
return a + b;
}
public static double add(double a, double b) {
return a + b;
}
public static long add(long a, long b) {
return a + b;
}
public static void main(String[] args) {
//方法的多載
System.out.println(Integer.MAX_VALUE);//整型最大值
System.out.println(add(2, 6));//整型相加
System.out.println(add(3.14, 2.86));//浮點數相加
System.out.println(add(2147483648L,2147483649L));//長整型相加
}
}

這種特征叫做多載( overloading,) 如果多個方法有相同的名字、 不同的引數,便產生了多載,編譯器必須挑選出具體執行哪個方法,它通過用各個方法給出的引數型別與特定方法呼叫所使用的值型別進行匹配來挑選出相應的方法,如果編譯器找不到匹配的引數, 就會產生編譯時錯誤,因為根本不存在匹配, 或者沒有一個比其他的更好,這個程序被稱為多載決議(overloading resolution),
🍁多載規則:
- 方法名相同
- 方法的引數不同(引數個數或者引數型別)
- 方法的回傳值型別不影響多載.
🍨3.Java方法的遞回
一個方法在執行程序中呼叫自身, 就稱為 “遞回”.
遞回相當于數學上的 “數學歸納法”, 有一個起始條件, 然后有一個遞推公式.
🍁例如, 我們求 N!
起始條件: N = 1 的時候, N! 為 1. 這個起始條件相當于遞回的結束條件.
遞回公式: 求 N! , 直接不好求, 可以把問題轉換成 N! => N * (N-1)!

public class testBlog {
public static int factorial(int n) {
if (n == 1) {
return 1;
}
return n * factorial(n - 1);
}
public static void main(String[] args) {
//遞回,n的階乘
System.out.println(factorial(5));
}
}
測驗一下,5!= 120,看看對不對,

🍦3.1斐波拉契數列
斐波那契數列,又稱黃金分割數列,指的是這樣一個數列:0、1、1、2、3、5、8、13、21、34、……在數學上,斐波納契數列以如下被以遞回的方法定義:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)在現代物理、準晶體結構、化學等領域,斐波納契數列都有直接的應用,為此,美國數學會從1963起出版了以《斐波納契數列季刊》為名的一份數學雜志,用于專門刊載這方面的研究成果,
特別指出:第0項是0,第1項是第一個1,這個數列從第3項開始,每一項都等于前兩項之和,
🍁斐波拉契數列的通項公式為:F(N) = F(N - 1) + F(N -2)
🍁起始條件:N = 0,F(0) = 0; N = 1,F(1) = 1;
🍁遞回實作:
public class testBlog {
public static int fib1(int n) {
if (n == 0 || n == 1) {
return n;
}
return fib1(n - 1) + fib1(n - 2);
}
public static void main(String[] args) {
//斐波拉契數列
for (int i = 0; i < 13; i++) {
System.out.print(fib1(i) + " ");
}
}
}

但是使用遞回實作斐波拉契數列,求后面的項會變得越來越慢,因為會進行大量重復的項的計算,
🍁推薦使用迭代的方法實作:
public class testBlog {
//fib1遞回,fib2迭代
public static int fib1(int n) {
if (n == 0 || n == 1) {
return n;
}
return fib1(n - 1) + fib1(n - 2);
}
public static int fib2(int n) {
if (n == 0 || n == 1) {
return n;
}
int f0 = 0;
int f1 = 1;
int fn = 0;
while (n - 1 != 0) {
fn = f0 + f1;
f0 = f1;
f1 = fn;
n--;
}
return fn;
}
public static void main(String[] args) {
//斐波拉契數列
for (int i = 0; i < 13; i++) {
System.out.print(fib1(i) + " ");//遞回結果
}
System.out.println();
for (int i = 0; i < 13; i++) {
System.out.print(fib2(i) + " ");//迭代結果
}
}
}

🍦3.2青蛙跳臺階問題
🍧3.2.1題目描述及思路
🍁題目:一只青蛙一次可以跳上1級臺階,也可以跳上2級臺階,求該青蛙跳上一個n級的臺階總共有多少種跳法?
解題思路
1.當n=1的時,很明顯青蛙只有一種跳法,
2.當n=2時,青蛙有兩種選擇,一是每次跳1級臺階,跳兩次,二是直接跳兩級臺階,一步到位,所以,一共有兩種跳法,
3.當n>2時,我們不妨把上n級臺階的跳法記為一個函式f(n),青蛙在第一次跳的時候有兩個選擇,即跳一級臺階或跳兩級臺階,當青蛙選擇第一次跳一級臺階時,跳完后還剩n-1級臺階,在此情況下,跳法的數目為f(n-1);當青蛙選擇第一次跳兩級臺階時,跳完后還剩n-2級臺階,在此情況下,跳法數目為f(n-2),所以,我們可以推出青蛙跳n級臺階的跳法總數為f(n)=f(n-1)+f(n-2),
到這里我們就能使用求斐波拉契數列的方法來求青蛙跳n級臺階的跳法,
🍁若把條件修改成一次可以跳一級,也可以跳2級…也可以跳上n級呢?
解題思路
盡管條件改成每次跳的臺階級數不受限,但是換湯不換藥,思考的方法是一樣的,
1.當n=1或n=2時,青蛙跳臺階跳法次數和沒修改條件時是一樣的,n=1有一種跳法,n=2有兩種跳法,
2.當n>2時,同理我們將青蛙跳n級臺階時的跳法記成函式f(n),但是青蛙在第一次的選擇不僅僅是跳1級和跳2級,它還可以選擇跳3,4,5,…,n級,所以青蛙跳一次后還會剩n-1,n-2,n-3,…,2, 1, 0級臺階,
此時,f(n)=f(n-1)+f(n-2)+f(n-3)+…+f(2)+f(1)+1
同理,f(n-1)=f(n-2)+f(n-3)+f(n-4)+…+f(2)+f(1)+1
合并上面兩個式子得,f(n)=2*f(n-1)
3.根據2的推論得出一個等比數列,由此我們還可以進一步推導:
🍁推導1:f(n)=f(n-1)+f(n-2)+f(n-3)+…+f(2)+f(1)+1
=1+f(1)+f(2)+…+f(n-2)+f(n-1)
=1+20*f(1)+21*f(1)+…+2n-3*f(1)+2n-2*f(1)
=1+(20+21+22+…+2n-3+2n-2)
=1+(2n-1-1)
=2n-1
f(1) = 1,f(2) = 2,f(n)為公比的2的等比數列(n>2)
🍁推導2:f(1) = 20, f(2) = 21, f(3) = 22…, f(n-1) = 2n-2, f(n) = 2n-1
🍧3.2.2代碼演示
public class testBlog {
//frog1遞回,frog2迭代
public static int frog1(int n) {
if (n <= 2) {
return n;
}
return frog1(n - 1) + frog1(n - 2);
}
public static int frog2(int n) {
if (n == 1 || n == 2) {
return n;
}
int f1 = 1;
int f2 = 2;
int fn = 0;
while (n - 2 != 0) {
fn = f1 + f2;
f1 = f2;
f2 = fn;
n--;
}
return fn;
}
public static int frogPlus1(int n) {
if (n == 1) {
return n;
}
return 2 * frogPlus1(n - 1);
}
public static int frogPlus2(int n) {
if (n == 1) {
return n;
}
int f1 = 1;
int fn = 0;
while (n - 1 != 0) {
fn = 2 * f1;
f1 = fn;
n--;
}
return fn;
}
public static int frogPlus3(int n) {
return (int)Math.pow(2, n - 1);
}
public static void main(String[] args) {
//青蛙跳臺階
for (int i = 1; i < 13; i++) {
System.out.print(frog1(i) + " ");//青蛙跳臺階遞回結果
}
System.out.println();
for (int i = 1; i < 13; i++) {
System.out.print(frog2(i) + " ");//青蛙跳臺階迭代結果
}
System.out.println();
for (int i = 1; i < 13; i++) {
System.out.print(frogPlus1(i) + " ");//青蛙跳臺階變式遞回結果
}
System.out.println();
for (int i = 1; i < 13; i++) {
System.out.print(frogPlus2(i) + " ");//青蛙跳臺階變式迭代結果
}
System.out.println();
for (int i = 1; i < 13; i++) {
System.out.print(frogPlus3(i) + " ");//青蛙跳臺階變式結論結果
}
}
}

🍦3.3漢諾塔問題
🍧3.3.1問題描述及思路
Hanoi(漢諾)塔問題,古代有一個梵塔,塔內有3個座A,B,C,開始時A座上有64個盤子,盤子大小不等,大的在下,小的在上,有一個先知想把這64個盤子從A座移到C座,但規定每次只允許移動一個盤,且在移動程序中在3個座上都始終保持大盤在下,小盤在上,在移動程序中可以利用B座,你能幫這位先知實作他的想法嗎?要求編程式輸出移動盤子的步驟,
🍁解題思路:
這位先知會這樣想: 假如有另外一位先知能有辦法將上面63個盤子從A座移到B座,那么,問題就解決了,此時先知只須這樣做:
① 聯系他的好朋友第2個先知將63個盤子從A座移到B座;
② 自己將1個盤子(最底下的、最大的盤子)從A座移到C座;
③ 再讓第2個先知將63個盤子從B座移到C座,
第2個先知又想: 如果有人能將62個盤子從一個座移到另一座,我就能將63個盤子從A座移到B座,他是這樣做的:
① 聯系他的好朋友第3個先知將62個盤子從A座移到C座;
② 自己將1個盤子從A座移到B座;
③ 再讓第3個先知將62個盤子從C座移到B座,
……
以此類推

為了便于理解,我們將盤子數量降低到3個,所以首先分析將A座上3個盤子移到C座上的程序:

① 將A座上2個盤子移到B座上(借助C座),
② 將A座上1個盤子移到C座上,
③ 將B座上2個盤子移到C座上(借助A座),

其中第②步可以直接實作,第①步又可用遞回方法分解為:
- 將A座上1個盤子從A座移到C座;
- 將A座上1個盤子從A座移到B座;
- 將C座上1個盤子從C座移到B座,
第③步可以分解為:
- 將B座上1個盤子從B座移到A座上;
- 將B座上1個盤子從B座移到C座上;
- 將A座上1個盤子從A座移到C座上,
將以上綜合起來,可得到移動3個盤子的步驟為:
A→C,A→B,C→B,A→C,B→A,B→C,A→C,
共經歷7步,由此可推出: 移動n個盤子要經歷(2n-1)步,
🍧3.3.2代碼演示
🍁由上面的分析可知: 將n個盤子從A座移到C座可以分解為以下3個步驟:
① 將A座上n-1個盤借助C座先移到B座上;
② 把A座上剩下的一個盤移到C座上;
③ 將n-1個盤從B座借助于A座移到C座上,
🍁可以把上面3個步驟分成兩類操作:
① 將n-1個盤從一個座移到另一個座上(n>1),這就是先知讓他的朋友第2個先知做的作業,它是一個遞回的程序,即先知將任務層層下放,直到第64個先知為止,——hanoi函式
② 將1個盤子從一個座上移到另一座上,這是先知自己做的作業,——move函式
public class testBlog {
public static void move(char m, char n) {
System.out.println(m + "->" + n);
}
public static void hanoi(int num, char a, char b, char c) {
if (num == 1) {
move(a, c);
return;
}
hanoi(num - 1, a, c, b);
move(a, c);
hanoi(num - 1, b, a, c);
}
public static void main(String[] args) {
//Hanoi(漢諾)塔問題,古代有一個梵塔,塔內有3個座A,B,C,
//開始時A座上有64個盤子,盤子大小不等,大的在下,小的在上,
//有一個先知想把這64個盤子從A座移到C座,但規定每次只允許移動一個盤,
//且在移動程序中在3個座上都始終保持大盤在下,小盤在上,
//在移動程序中可以利用B座,你能幫這位先知實作他的想法嗎?
//要求編程式輸出移動盤子的步驟,
int num = 3;
hanoi(3,'A', 'B', 'C');
}
}
看看3個盤子的漢諾塔程式是怎么移動的:

與我們推演出來的移動順序一致!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/333785.html
標籤:java
上一篇:cgb2108-day17
