詳細介紹:JAVA實驗課程第五次作業分析與代碼示例
1.作業內容
1.1 數組中唯一的數字
給定一個整數數組,其中除了某個元素只出現一次外,其余每個元素均出現兩次。請找出那個只出現一次的元素。
1.2 驗證回文串
編寫一個方法,判斷一個字符串是否為回文串?;匚拇侵刚x和反讀都相同的字符串,忽略字母大小寫和非字母數字字符(字母和數字為有效字符)。
示例:輸入:"A man, a plan, a canal: Panama"輸出:true(忽略非字符后為 “amanaplanacanalpanama”,正反讀相同)
輸入:"race a car"輸出:false
1.3字符串壓縮
要求:實現一個字符串壓縮算法:將連續重復的字符替換為 “字符 + 重復次數”。如果壓縮后的字符串長度不小于原字符串,則返回原字符串。
示例:輸入:"aabcccccaaa"輸出:"a2b1c5a3"輸入:"abc"輸出:“abc” 解釋:壓縮后為 “a1b1c1”,長度更長。
1.4二維數組的轉置
編寫一個 Java 程序,實現二維整數數組的轉置操作。轉置是指將原數組的行變為列、列變為行(即原數組中位于(i,j)位置的元素,轉置后位于(j,i)位置)。
注意:原數組可能不是方陣(行數和列數可以不同),轉置后新數組的行數等于原數組的列數,新數組的列數等于原數組的行數。
1.5數組元素移動
編寫一個 Java 程序,將整數數組中所有的 0 元素移動到數組末尾,同時保持非 0 元素的相對順序不變。不能創建新的數組,必須在原數組上操作。
1.6數字反轉與回文判斷
編寫程序完成兩個
任務:
將一個整數反轉(如 123→321,-456→-654,1200→21);
判斷反轉后的數字是否為回文數(即反轉前后數字相同,如 121 反轉后還是 121,是回文數;123 反轉后是 321,不是回文數,-12321也是回文數)。
1.7 中秋國慶雙節禮品分配
題目場景
中秋與國慶雙節期間,班級要給同學們分配節日禮品,禮品包含 3 類:月餅禮盒、國旗徽章、中秋燈籠。已知每種禮品的總數量和班級人數,要求按以下規則分配禮品,并統計結果:
先給每位同學每種禮品各分配 1 份(確保每人都有基礎禮品);
分配完基礎禮品后,若某類禮品還有剩余,則按 “從第 1 位同學到最后 1 位同學” 的順序,每人再額外分配 1 份,直到該類禮品分完(剩余不足 1 份時停止);
最后輸出每位同學獲得的各類禮品數量、總禮品數,以及每種禮品的剩余數量。
示例:
輸入:
班級人數:5 人
禮品總數:月餅禮盒 10 份、國旗徽章 8 份、中秋燈籠 5 份
分配過程:
基礎分配:每人各得 1 份月餅、1 份徽章、1 份燈籠,共消耗 5 份月餅、5 份徽章、5 份燈籠;
剩余禮品:月餅剩 5 份、徽章剩 3 份、燈籠剩 0 份;
額外分配:
月餅:按順序給 5 人各再分 1 份,剛好分完;
徽章:按順序給前 3 人各再分 1 份,剛好分完;
燈籠:無剩余,不分配。
2. 題目分析與解答
2.1 數組中唯一的數字
a.計數法
分析
這一道題我們要計算每個元素出現的次數,出現2次代表沒問題。因此,我們只需要記錄下來我們每一個元素出現的次數即可。
1.使用哈希表(HashMap)記錄每個數字出現的次數,最后找出次數為 1 的數字。
2.使用一個數組記錄。我們可以初始化一個全為0的數組,比如當2出現一次的時候,我們可以讓arr[2]++,最后我們便利數組找出數組中值為1的下標即可。
這兩種方式大家都可以嘗試,但是由于我們還沒有學習到哈希表,所以此處我們展示上訴第二點的代碼。
代碼
由于本題真正考察的是第二種解法,此處僅僅展示主要函數功能的寫法,主函數放在了下一個代碼中,調用的話可以模仿亦或運算中的方式調用。
public static int findUniqueNumber2(int[] nums){
int result[] = new int[100];
for (int num : nums) {
result[num]++;
}
for (int i = 0; i < result.length; i++) {
if(result[i] == 1){
return i;
}
}
return -1;
}
運行截圖

b.亦或運算
分析:
利用異或運算的特性,相同數字異或結果為 0,0 與任何數字異或結果為該數字本身,遍歷數組對所有元素進行異或操作即可得到唯一的數字。
public static void main(String[] args) {
int[] nums = {4, 1, 2, 1, 2};
System.out.println("數組中唯一的數字是: " + findUniqueNumber(nums));
// 可以添加更多測試用例
int[] nums2 = {7, 3, 5, 4, 5, 3, 4};
System.out.println("另一組測試中唯一的數字是: " + findUniqueNumber(nums2));
}
// 找出數組中唯一的數字
public static int findUniqueNumber(int[] nums) {
int result = 0;
// 利用異或運算特性:a^a=0,a^0=a,異或滿足交換律和結合律
for (int num : nums) {
result ^= num;
}
return result;
}
2.2 驗證回文串
分析
- 先過濾掉非字母數字字符并轉為小寫。
- 然后使用雙指針從兩端向中間比較,判斷是否為回文串。
代碼解釋:
- Character.isLetterOrDigit() 判斷是否是字母或者是數字,如果不使用此方法,也可以自己寫判斷語句,判斷某個字母是否是(字母>=‘A’ && <=‘Z’) || (字母>=‘a’ && <=‘z’ )||(字母>=‘0’ && <=‘9’ )
- toLowerCase() 轉換為小寫字母。
代碼
public static void main(String[] args) {
String s1 = "A man, a plan, a canal: Panama";
String s2 = "race a car";
System.out.println("\"" + s1 + "\" 是否為回文串: " + isPalindrome(s1));
System.out.println("\"" + s2 + "\" 是否為回文串: " + isPalindrome(s2));
}
// 驗證回文串
public static boolean isPalindrome(String s) {
// 過濾非字母數字字符并轉為小寫
StringBuilder filtered = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isLetterOrDigit(c)) {
filtered.append(Character.toLowerCase(c));
}
}
// 雙指針判斷是否回文
int left = 0;
int right = filtered.length() - 1;
while (left < right) {
if (filtered.charAt(left) != filtered.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
2.3 字符串壓縮
分析
字符串 String還沒學過,先簡單看看。
根據題目意思,可以分為兩部分:
-1.遍歷字符串統計連續相同字符的個數,構建壓縮后的字符串。
-2.最后比較壓縮前后的長度,返回較短的那個。
代碼
public static void main(String[] args) {
String str1 = "aabcccccaaa";
String str2 = "abc";
String str3 = "aaaaabbbbbccccc";
System.out.println("\"" + str1 + "\" 壓縮后: " + compressString(str1));
System.out.println("\"" + str2 + "\" 壓縮后: " + compressString(str2));
System.out.println("\"" + str3 + "\" 壓縮后: " + compressString(str3));
}
// 字符串壓縮
public static String compressString(String s) {
if (s.length() <= 1) {
return s;
}
StringBuilder compressed = new StringBuilder();
char current = s.charAt(0);
int count = 1;
for (int i = 1; i < s.length(); i++) {
if (s.charAt(i) == current) {
count++;
} else {
compressed.append(current).append(count);
current = s.charAt(i);
count = 1;
}
}
// 添加最后一組字符
compressed.append(current).append(count);
// 如果壓縮后長度不小于原長度,返回原字符串
return compressed.length() < s.length() ? compressed.toString() : s;
}
2.4 二維數組的轉置
分析
轉置的本質是交換數組的行索引和列索引。例如原數組中matrix[i][j]的元素,在轉置后的數組中會位于transposed[j][i]的位置。
代碼實現
- 實現步驟:
首先確定原數組的行數(rows)和列數(cols);
創建轉置后的新數組,其行數為原數組的列數,列數為原數組的行數;
通過嵌套循環遍歷原數組,將每個元素放入新數組的對應位置;
提供printMatrix方法用于打印數組,方便觀察轉置效果。 - 代碼:
public static void main(String[] args) {
// 測試用例1:2行3列的數組
int[][] matrix1 = {
{1, 2, 3},
{4, 5, 6}
};
System.out.println("原數組(2行3列):");
printMatrix(matrix1);
int[][] transposed1 = transpose(matrix1);
System.out.println("轉置后(3行2列):");
printMatrix(transposed1);
// 測試用例2:3行3列的方陣
int[][] matrix2 = {
{10, 20, 30},
{40, 50, 60},
{70, 80, 90}
};
System.out.println("\n原數組(3行3列):");
printMatrix(matrix2);
int[][] transposed2 = transpose(matrix2);
System.out.println("轉置后(3行3列):");
printMatrix(transposed2);
// 測試用例3:1行5列的數組
int[][] matrix3 = {
{1, 2, 3, 4, 5}
};
System.out.println("\n原數組(1行5列):");
printMatrix(matrix3);
int[][] transposed3 = transpose(matrix3);
System.out.println("轉置后(5行1列):");
printMatrix(transposed3);
}
// 二維數組轉置的核心方法
public static int[][] transpose(int[][] matrix) {
// 原數組的行數和列數
int rows = matrix.length;
// 若原數組為空,直接返回空數組
if (rows == 0) {
return new int[0][0];
}
int cols = matrix[0].length;
// 創建轉置后的新數組:行數=原列數,列數=原行數
int[][] transposed = new int[cols][rows];
// 遍歷原數組,填充轉置后的數組
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
// 原數組(i,j)位置的元素 → 轉置后(j,i)位置
transposed[j][i] = matrix[i][j];
}
}
return transposed;
}
// 輔助方法:打印二維數組
public static void printMatrix(int[][] matrix) {
for (int i = 0; i < matrix.length; i++) {
System.out.print("[ ");
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println("]");
}
}
2.5 數組元素移動
分析
分兩步操作,首先將所有非 0 元素移到前面,然后將剩余位置填充 0,確保在原數組上操作。
public static void main(String[] args) {
int[] arr1 = {0, 1, 0, 3, 12};
int[] arr2 = {0, 0, 1};
int[] arr3 = {1, 2, 3};
System.out.print("原數組1: ");
printArray(arr1);
moveZeros(arr1);
System.out.print("移動0之后: ");
printArray(arr1);
System.out.print("\n原數組2: ");
printArray(arr2);
moveZeros(arr2);
System.out.print("移動0之后: ");
printArray(arr2);
System.out.print("\n原數組3: ");
printArray(arr3);
moveZeros(arr3);
System.out.print("移動0之后: ");
printArray(arr3);
}
// 打印數組
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
if (i < arr.length - 1) {
System.out.print(", ");
}
}
System.out.println();
}
// 數組元素移動:將所有0移到末尾
public static void moveZeros(int[] nums) {
int nonZeroIndex = 0;
// 把所有非0元素移到前面
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
nums[nonZeroIndex] = nums[i];
nonZeroIndex++;
}
}
// 剩余位置填充0
for (int i = nonZeroIndex; i < nums.length; i++) {
nums[i] = 0;
}
}
提示
能不能交換,遇到0的時候就和數組最后一個數字交換。
仔細想想,是不行的,題目要求順序不能變,這樣就變順序了。
2.6 數字反轉與回文判斷
分析:
處理負數情況,通過取余和乘 10 操作反轉數字,最后比較原數字和反轉后的數字是否相等來判斷是否為回文數。
思考:是否可以使用第二題中的方式?為何不使用第二題中的方式?
代碼解析:
public static void main(String[] args) {
int num1 = 12321;
int num2 = -123;
int num3 = 1200;
int num4 = -12321;
reverseAndCheckPalindrome(num1);
reverseAndCheckPalindrome(num2);
reverseAndCheckPalindrome(num3);
reverseAndCheckPalindrome(num4);
}
// 數字反轉與回文判斷
public static void reverseAndCheckPalindrome(int num) {
int original = num;
int reversed = 0;
boolean isNegative = num < 0;
// 處理負數
if (isNegative) {
num = -num;
}
// 反轉數字
while (num != 0) {
int digit = num % 10;
reversed = reversed * 10 + digit;
num /= 10;
}
// 恢復負數
if (isNegative) {
reversed = -reversed;
}
// 判斷是否為回文數
boolean isPalindrome = original == reversed;
System.out.println(original + " 反轉后: " + reversed + "," +
(isPalindrome ? "是回文數" : "不是回文數"));
}
2.7 中秋國慶雙節禮品分配
輸出示例:

代碼實現
public class FestivalGiftAllocator {
public static void main(String[] args) {
// 1. 定義節日相關數據:禮品名稱、總數量,班級人數
String[] giftNames = {"月餅禮盒", "國旗徽章", "中秋燈籠"}; // 雙節禮品類型
int[] totalGifts = {10, 8, 5}; // 每種禮品的總數量(對應上面的禮品順序)
int studentCount = 5; // 班級人數
// 2. 創建數組存儲每位同學的禮品數量:studentGifts[同學索引][禮品類型索引]
int[][] studentGifts = new int[studentCount][giftNames.length];
// 創建數組存儲每種禮品的剩余數量
int[] remainingGifts = new int[giftNames.length];
// 3. 第一步:基礎分配(每人每種禮品各1份)
for (int i = 0; i < giftNames.length; i++) {
// 若該類禮品總數 >= 人數,才能給每人分1份;否則無法完成基礎分配(題目默認總禮品足夠基礎分配)
if (totalGifts[i] >= studentCount) {
for (int j = 0; j < studentCount; j++) {
studentGifts[j][i] = 1; // 每人該禮品分1份
}
// 計算基礎分配后的剩余數量
remainingGifts[i] = totalGifts[i] - studentCount;
}
}
// 4. 第二步:額外分配(剩余禮品按順序分給同學,每人每次1份)
for (int i = 0; i < giftNames.length; i++) {
// 若該類禮品有剩余,才進行額外分配
if (remainingGifts[i] > 0) {
int giftLeft = remainingGifts[i]; // 當前剩余的禮品數
int studentIndex = 0; // 從第1位同學開始(索引0)
// 循環分配,直到禮品分完或所有同學都額外分過
while (giftLeft > 0 && studentIndex < studentCount) {
studentGifts[studentIndex][i] += 1; // 給當前同學額外分1份
giftLeft -= 1; // 剩余禮品減1
studentIndex += 1; // 下一位同學
}
// 更新剩余禮品數(此時giftLeft應為0,除非禮品沒分完,但題目默認可分完)
remainingGifts[i] = giftLeft;
}
}
// 5. 輸出每位同學的禮品分配結果
for (int i = 0; i < studentCount; i++) {
int total = 0; // 統計當前同學的總禮品數
// 拼接該同學的各類禮品信息
StringBuilder giftInfo = new StringBuilder();
for (int j = 0; j < giftNames.length; j++) {
giftInfo.append(giftNames[j]).append(studentGifts[i][j]).append("份");
if (j < giftNames.length - 1) {
giftInfo.append(",");
}
total += studentGifts[i][j]; // 累加總禮品數
}
// 輸出結果(注意:同學編號從1開始,索引從0開始,所以+1)
System.out.println("第" + (i + 1) + "位同學:" + giftInfo + ",總禮品數" + total + "份");
}
// 6. 輸出剩余禮品
System.out.println("\n剩余禮品:");
for (int i = 0; i < giftNames.length; i++) {
System.out.println(giftNames[i] + ":" + remainingGifts[i] + "份");
}
}
}
浙公網安備 33010602011771號