WeHelp是台灣的軟體工程師社群,它的網站有程式解題系統 WeHelp Coding,提供基礎的程式練習題,適合新手熟悉語法、建立寫程式的邏輯思維。網站不會保留使用者的作答結果,因此我在這裡留下自己的解答,以及參考AI後修改的解法。目前系統提供Python和JavaScript兩種程式語言解題,本文用JavaScript解題,附上題目和註解供大家參考。
21. 最大連續 0 的數量
輸入一個只包含 0 和 1 的陣列 / 列表,你的函式要找出並回傳最大連續 0 的數量。
輸入範例:[0, 1, 0, 0, 0, 1, 0, 1]。回傳:3
輸入範例:[1, 1, 1]。回傳:0
輸入範例:[0, 0, 0, 0, 1, 0]。回傳:4
// @param nums:{[Integer]}
// @return :{Integer}
// 用陣列儲存連續0的數量
function findMaxZero(nums){
let array = [0];
let count = 0;
for (let i=0; i<nums.length; i++){
if (nums[i]==0) count++; //抓到0就+1
else { // 沒抓到0就把計數存進陣列後歸零
array.push(count);
count = 0;
}
}
array.push(count); // 把最後一個計數存進去
return Math.max(...array); //回傳陣列的最大值
}
// 直接紀錄最大值
function findMaxZero(nums){
let count, maxCount = 0;
for (let i=0; i<nums.length; i++){
if (nums[i] == 0) count++;
else{
if(count > maxCount) maxCount = count;
count = 0;
}
}
return maxCount > count ? maxCount : count;
}
22. 平方根,四捨五入取整數
輸入一個正整數,你的函式可以計算這個正整數的平方根,但請四捨五入到整數的部份。
輸入範例:9。回傳:3
輸入範例:12。回傳:3
輸入範例:15。回傳:4
// @param n:{Integer}
// @return :{Integer}
// 線性搜尋 從1開始遞增 檢驗平方是否小於n 因為有四捨五入條件所以必須減0.5再檢測
function sqrt(n){
let ans = 1;
for (let i=1; (i-0.5)**2 <= n; i++){
ans = i;
}
return ans;
}
// 二分法 參考AI和網路解說 做法比較複雜
// 平方根必定介於1~n之間 取兩者中間數m
// 若m平方比較大表示答案在1~m之間 若比較小表示在m~n之間
// 這樣反覆進行就會逼近答案
function sqrt(n){
let a = 1;
let b = n;
let m;
while (b-a > 0.001){
m = (a+b)/2;
if (m*m > n) b = m;
else if (m*m < n) a = m;
else if (m*m == n) return m;
}
return Math.round(m);
}
23. 總秒數轉換為日、時、分、秒
輸入一個非負整數代表一段時間的總秒數,請將這個總秒數轉換為:日、時、分、秒,四個欄位,按照順序用陣列 / 列表的格式輸出。
輸入範例:0。回傳:[0, 0, 0, 0]
輸入範例:65。回傳:[0, 0, 1, 5]
輸入範例:7500。回傳:[0, 2, 5, 0]
輸入範例:100000。回傳:[1, 3, 46, 40]
// @param sec:{Integer}
// @return :{[Integer]}
function convertSeconds(sec){
let array =[];
array[0] = Math.floor(sec/60/60/24);
array[1] = Math.floor(sec/60/60%24);
array[2] = Math.floor(sec/60%60);
array[3] = sec%60;
return array;
}
24. Stack 堆疊的基本操作
Stack 堆疊是一種基礎資料結構,我們使用陣列 / 列表來實作時,定義 Push 操作,代表將資料放到陣列 / 列表的尾巴;定義 Pop 操作,代表將資料從陣列 / 列表的尾巴取出。
輸入一個逗號隔開的字串,每個欄位代表一個操作,若是 Push 操作,會空一格後表示要操作的整數資料。你的函式必須使用陣列 / 列表實作一個 Stack,回傳經過輸入的操作之後產生的最終結果。
請注意最後放進 Stack 中的資料是整數的型態。
輸入範例:"push 5,push 4,pop"。回傳:[5]
輸入範例:"pop,push 1,push -3,push 5,pop,push 10"。回傳:[1, -3, 10]
輸入範例:"push 3,push -2,pop,pop,pop"。回傳:[]
// @param ops:{String}
// @return :{[Integer]]}
// 先分割為陣列再逐項檢視
// 我原本用substring檢驗 chatGPT建議用startsWith更簡潔
function processStackOperations(ops){
let stack = [];
let array = ops.split(",");
for (let i=0; i<array.length; i++){
let a = array[i];
if (a.startsWith("push")){
let num = a.split(" ")[1];
stack.push(parseInt(num));
}else if (a.startsWith("pop")){
stack.pop();
}
}
return stack;
}
25. Queue 佇列的基本操作
Queue 佇列是一種基礎資料結構,我們使用陣列 / 列表來實作時,定義 Enq (Enqueue) 操作,代表將資料放到陣列 / 列表的尾巴;定義 Deq (Dequeue) 操作,代表將資料從陣列 / 列表的前面取出。
輸入一個逗號隔開的字串,每個欄位代表一個操作,若是 Enq (Enqueue) 操作,會空一格後表示要操作的整數資料。你的函式必須使用陣列 / 列表實作一個 Queue,回傳經過輸入的操作之後產生的最終結果。
請注意最後放進 Queue 中的資料是整數的型態。
輸入範例:"enq 5,enq 4,deq"。回傳:[4]
輸入範例:"deq,enq 1,enq -3,enq 5,deq,enq 10"。回傳:[-3, 5, 10]
輸入範例:"enq 3,enq -2,deq,deq,deq"。回傳:[]
// @param ops:{String}
// @return :{[Integer]]}
// 與前一題邏輯類似 改用forEach取代for-loop
function processQueueOperations(ops){
let array = ops.split(",");
let queue = [];
array.forEach( a =>{
if (a.startsWith("enq"))
queue.push(+a.split(" ")[1]);
else if (a.startsWith("deq"))
queue.shift(); // shift()刪除頭
});
return queue;
}
26. 檢查整數是否落在某個區間
輸入一個整數區間的最小值和最大值,以及要檢查的目標數,你的函式能判斷目標數是否落在最小值和最大值的中間,包含最小和最大值。可以假設輸入的最大值一定大於最小值。
輸入範例:最小 5,最大 10,目標 8。回傳:真
輸入範例:最小 -5,最大 5,目標 -6。回傳:假
輸入範例:最小 2,最大 100,目標 2。回傳:真
// @param min:{Integer}
// @param max:{Integer}
// @param target:{Integer}
// @return :{Boolean}
function isInside(min, max, target){
if (target >= min && max >= target) return true;
else return false;
}
// 條件運算可以一行解決
function isInside(min, max, target){
return target >= min && max >= target ;
}
27. 檢查兩個區間是否重疊
輸入兩個陣列 / 列表,分別代表兩個整數區間的最小值和最大值 [min1, max1] 和 [min2, max2],你的函式能判斷兩個整數區間是否重疊,包含最小或最大值落在同一個整數的狀況。可以假設每個區間的最大值一定大於最小值。
輸入範例:[5, 10],[9, 11]。回傳:真
輸入範例:[-5, 5],[8, 10]。回傳:假
輸入範例:[-5, 5],[-6, -5]。回傳:真
// @param range1:{[Integer]}
// @param range2:{[Integer]}
// @return :{Boolean}
// 區間重疊表示A數列的上限>=B數列的下限 交換驗證都成立就通過
function isOverlapping(range1, range2){
return range1[1]>=range2[0] && range2[1]>=range1[0];
}
28. 撲克牌比點數大小
假設在一個撲克牌遊戲中,不考慮花色,點數由小到大的排序是 2、3、4、...、10、J、Q、K、A。輸入兩個字串,依序代表兩張撲克牌的點數,你的函式可以判斷是否第一張比第二張大,若是,回傳真;否則,回傳假。
輸入範例:"K"、"3"。回傳:真
輸入範例:"J"、"Q"。回傳:假
輸入範例:"2"、"A"。回傳:假
輸入範例:"10"、"10"。回傳:假
// @param f1:{String}
// @param f2:{String}
// @return :{Boolean}
function comparePokerFigure(f1, f2){
const poker = ["2","3","4","5","6","7","8","9","10","J","Q","K","A"];
return poker.indexOf(f1) > poker.indexOf(f2) ;
}
29. 撲克牌比點數、花色大小
假設在一個撲克牌遊戲中,點數由小到大的排序是 2、3、4、...、10、J、Q、K、A。若點數相同,則考慮花色,花色由小到大的排序是 C ( 梅花 )、D ( 方塊 )、H ( 紅心 )、S ( 黑桃 )。輸入兩個字串,依序代表兩張撲克牌的點數和花色,你的函式可以判斷是否第一張比第二張大,若是,回傳真;否則,回傳假。
輸入範例:"KC"、"3H"。回傳:真
輸入範例:"JS"、"QS"。回傳:假
輸入範例:"2S"、"2D"。回傳:真
輸入範例:"10C"、"10H"。回傳:假
// @param c1:{String}
// @param c2:{String}
// @return :{Boolean}
function comparePokerCard(c1, c2){
const ranks = ["2","3","4","5","6","7","8","9","10","J","Q","K","A"];
const suits = ["C","D","H","S"];
const rank1 = ranks.indexOf(c1.slice(0, -1)); //取數字:從頭到倒數第二字
const suit1 = suits.indexOf(c1.slice(-1)); // 取花色:最後一個字
const rank2 = ranks.indexOf(c2.slice(0, -1));
const suit2 = suits.indexOf(c2.slice(-1));
if (rank1 > rank2){ //點數大
return true;
}else if (rank1 < rank2){ //點數小
return false;
}else { //點數相同
return suit1 > suit2 ? true : false;
}
}
30. 二十四小時的推移
二十四小時的表示法中,整數 0 ~ 23 代表一天內的小時數。輸入一個 0 ~ 23 之間的整數,代表目前的小時數;以及一個任意整數,代表小時數的推移量。你的函式能夠計算並回傳經過推移後的小時數 ( 使用二十四小時表示法 )。
輸入範例:2、5。回傳:7
輸入範例:16、10。回傳:2
輸入範例:1、-5。回傳:20
輸入範例:3、-30。回傳:21
輸入範例:23、100。回傳:3
// @param current:{Integer}
// @param offset:{Integer}
// @return :{Integer}
// 解法一 如果是負的先加到正的 正的就取餘數
function addHours(current, offset){
let hour = (current+offset)%24;
while (hour <0){
hour += 24;
}
return hour;
}
// 解法二 不用迴圈但需要用數學推算
function addHours(current, offset){
let hour = current + offset;
if (hour >= 0) return hour%24;
if (hour <0) return (24-((-hour)%24))%24;
//如果(-hour)%24是0 會變成24 所以最後再%24
}