Java程式設計(2021春)——第二章課後題(選擇題+程式設計題)答案與詳解
第二章選擇題
Tip:選擇題部分我只針對部分我出錯的或我認為有價值的題目在此整理。
2.1 物件導向方法的特性
T1
題面
物件導向的程式設計方法採用了什麼樣的抽象方法構建程式的類與物件:
A 過程抽象
B 資料抽象
C 過程抽象與資料抽象
D 沒有采用任何的抽象方法
答案
B
詳解
物件導向程式設計方法的基本思想是使用類、物件、繼承、封裝和訊息等概念進行程式設計。它從現實世界客觀存在的事物(物件)出發來構造軟體系統。強調儘可能用人類自然的思維方式思考問題,認識問題,從而將現實世界中的事物抽象成系統中的類,作為系統的基本構成單元。這樣構建的系統能直接對映客觀世界,更符合現實世界的本來面貌。
物件導向的基本哲學是世界是由各種各樣具有自己的運動規律和內部狀態的物件所組成的;不同物件之間的相互作用和通訊構成了完整的現實世界。
從程式設計的角度看,物件導向的程式設計語言必須有描述物件及其相互之間的關係的語言成分。歸納起來即:系統中一切都是物件;物件是屬性及其操作的封裝體;物件可以按性質劃分為類,物件是類的例項;例項關係和繼承關係是物件之間的靜態關係;訊息傳遞是物件之間動態聯絡的唯一形式,也是計算的唯一形式;方法是訊息的序列。
在物件導向的程式設計過程中,開發者要從自己的使用角度和認識角度出發來定義類,從而模擬客觀世界的事物,並讓自己明白這種事物是用來做什麼的,對我們有什麼意義。用抽象的方法忽略一個事物中與目標類無關的那些方面,充分地注意與當前目標有關的方面。
T5
題面
Java的封裝性是通過什麼實現的:
A 訪問控制許可權
B 設計內部類
C 靜態域與靜態方法
D 包
答案
A
詳解
筆者查了一下,還沒查到為什麼,先mark一下。
2.2-1 類宣告與物件建立
無
2.2-2 資料成員
無
2.2-3 方法成員
無
2.2-4 包
無
2.2-5類的訪問控制許可權
T3
題面
下列程式碼在編譯時會發生錯誤,下面哪種修改可以更正錯誤:
class Test{
private int m;
public static void fun(){
System.out.println(m);
}
}
A 將private int m改成protected int m
B 將private int m改成public int m
C 將private int m改成static int m
D 將private int m改成int m
答案
C
詳解
fun
經過了static
修飾,是類方法(靜態方法),不可以呼叫例項變數。
2.3-1 物件初始化
無
2.3-2 記憶體回收
無
2.4列舉類
T2
題面
下面關於列舉型別,說法錯誤的是:
A 列舉值是類的物件
B 列舉中可以定義資料和方法
C 列舉類的values()方法用於獲得列舉型別的列舉值的陣列
D 列舉型別可以有public的建構函式
答案
D
詳解
建構函式即構造方法,而列舉型別中構造方法必須是包內私有或者私有的。
第二章程式設計題
T1 矩陣螺旋
題面
給定m × n個元素(m行,n列)的矩陣,以螺旋順序返回矩陣的所有元素。輸入為m n以及m*n的矩陣,輸出螺旋順序的所有元素
樣例輸入:
3 3
1 2 3
4 5 6
7 8 9
樣例輸出:
123698745
樣例解釋:
無
思考和詳解
本題筆者思考的時候說實話其實沒太用到Java物件導向的特性,基本上還是按照C語言的思考方式來寫的。只需要舉幾個例子,判斷一下條件即可模擬解決本題。
具體程式碼
import java.util.Scanner;
public class matrix {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m = 0;
int n = 0;
int flag = 1;
int ct = 0;
int cnt = 1;
m = in.nextInt();
n = in.nextInt();
int sum = m * n;
int[][] matrix = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
matrix[i][j] = in.nextInt();
}
}
in.close();
int i = 1;
int j = 1;
while ((++ct) <= sum) {
if (flag == 1) {
System.out.print(matrix[i][j++]);
if (j == n) {
flag = 2;
}
continue;
} else if (flag == 2) {
System.out.print(matrix[i++][j]);
if (i == m) {
flag = 3;
n--;
}
continue;
} else if (flag == 3) {
System.out.print(matrix[i][j--]);
if (j == cnt) {
flag = 4;
cnt++;
}
continue;
} else if (flag == 4) {
System.out.print(matrix[i--][j]);
if (i == cnt) {
flag = 1;
m--;
}
continue;
}
}
}
}
T2 組合數
題面
給定N個無重複的正整數,和目標數M,找出N中所有子集,使得每個子集的和是M,對於每個數而言,可以選多次,所有結果子集不能夠重複。輸入為2行,第一行為N和M,第二行為N個數,輸出為總共的子集數。
樣例輸入:
4 7
2 3 6 7
樣例輸出:
2
樣例解釋:
7=7
2+2+3=7
思考和詳解
本題使用簡單遞迴即可,由於沒有要求不重複,所以我們額外注意一下列舉的時候從當前元素開始。本題沒有說明給的無重複正整數一定是按順序給出的,但是筆者比較懶,沒寫sort
,但是還是過了,測試資料應該都是升序給的,不過標準來說還是應該排序一下的。
具體程式碼
import java.util.Scanner;
public class combination {
public static int cnt = 0;
public static int[] arr = new int[10005 + 1];
public static void func(int nowSum, int n, int ct, int target) {
if (nowSum == target) {
cnt++;
return;
} else if (nowSum > target)
return;
for (int i = ct; i <= n; i++) {
func(nowSum + arr[i], n, i, target);
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m;
int n;
n = in.nextInt();
m = in.nextInt();
for (int i = 1; i <= n; i++) {
combination.arr[i] = in.nextInt();
}
combination.func(0, n, 1, m);
System.out.println(combination.cnt);
}
}
T3 組合數2
題面
給定N個的正整數【可能有重複】,和目標數M,找出N中所有子集,使得每個子集的和是M,對於每個數,只能選一次,所有結果子集不能夠重複。輸入為2行,第一行為N和M,第二行為N個數,輸出為總共的子集數。
樣例輸入:
7 8
10 1 2 7 6 1 5
樣例輸出:
4
樣例解釋:
【1,7】
【1,2,5】
【2,6】
【1,1,6】
思考和詳解
本題在本章T2的基礎上略有改變,主要體現在以下兩點:
- 所給數字可能有重複。
- 每個數字只能用一次,對於重複數字則是至多用所給次數次,但方案彼此不可以重複。
需要改變的地方有如下:
- 需要對陣列排序,呼叫
java.import.Arrays
中的Arrays.sort()
方法,值得注意的是,呼叫該方法似乎預設對整個陣列進行排序,因此建議按照正好的大小進行初始化申請空間,並從角標0存入資料。 - 需要特殊處理陣列中連續的重複數字,以避免如1,1,1,1,2,2中選出了若干1,1,2這種情況。
- 需要注意不重複數字只能使用一次。
具體程式碼
import java.util.Arrays;
import java.util.Scanner;
class Main {
public static int cnt = 0;
public static int[] arr;
public static void func(int nowSum, int n, int ctt, int target) {
int flag;
int j = 0;
if (nowSum == target) {
Main.cnt++;
return;
} else if (nowSum > target)
return;
for (int i = ctt; i < n; i++) {
flag = 0;
if ((i + 1) < n && Main.arr[i] == Main.arr[i + 1]) {
flag = 1;
j = i;
while ((j + 1) < n && Main.arr[j] == Main.arr[j + 1]) {
j++;
}
}
if (flag == 0)
func(nowSum + arr[i], n, i + 1, target);
else {
for (int k = 1; k <= (j - i + 1); k++) {
func(nowSum + k * arr[i], n, j + 1, target);
}
i = j;
}
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m;
int n;
n = in.nextInt();
m = in.nextInt();
Main.arr = new int[n];
for (int i = 0; i < n; i++) {
Main.arr[i] = in.nextInt();
}
in.close();
Arrays.sort(arr);
Main.func(0, n, 0, m);
System.out.println(Main.cnt);
}
}