進階與經典題目


Posted by 小小碼農 on 2021-05-02

所有題目皆可忽略前面,直接從 functon solves(){} 開始看就好

Q1 好多星星

輸入為一個數字 N,請按照規律輸出正確圖形

N=1

*
N=2

*
**
N=3

*
**
***
....

N=10

*
**
***
****
*****
******
*******
********
*********
**********

輸入為一個正整數 N,1 <= N <= 301<=N<=30,請依照規律輸出正確圖形

Q1 解題

var readline = require("readline");
var rl = readline.createInterface({
  input: process.stdin,
});

var lines = [];

// 讀取到一行,先把這一行加進去 lines 陣列,最後再一起處理
rl.on("line", function (line) {
  lines.push(line);
});

// 輸入結束,開始針對 lines 做處理
rl.on("close", function () {
  solve(lines);
});

// 上面都不用管,只需要完成這個 function 就好,可以透過 lines[i] 拿取內容
function solve(lines) {
  printStars(Number(lines[0]));
}

function printStars(n) {
  let stars = "";
  for (let i = 1; i <= n; i++) {
    stars += "*";
    console.log(stars);
  }
}

Q1 解題思路

  1. 對於累加的東西,想到迴圈
  2. 使用空字串累加,每跑一次加一次星星

Q2 水仙花數

水仙花數(Narcissistic number)又被稱為自戀數或者是阿姆斯壯數,太數學的定義我們就不講了,詳情可以查維基百科。
比較白話的定義為:「一個 n 位數的數字,每一個數字的 n 次方加總等於自身」
例如說 153 是三位數,而 1^3 + 5^3 + 3^3 = 153, 所以它就是一個水仙花數
而 1634 是四位數,而 1^4 + 6^4 + 3^4 + 4^4 = 1634, 所以它也是一個水仙花數
而數字 0~9 也都是水仙花數,因為一位數 n 的 1 次方一定會等於自己
現在給你一個範圍 n 到 m,請你求出這範圍之中的水仙花數有哪些

輸入為兩個用空白分割的正整數 N 與 M,1 <= N <= M <= 10^6
請由小到大輸出從 N 到 M(包含 N 與 M)有哪些水仙花數,每個數字以空行分隔

Sample Input 1
5 200
5
6
7
8
9
153

Q2 解題

var readline = require("readline");
var rl = readline.createInterface({
  input: process.stdin,
});

var lines = [];

// 讀取到一行,先把這一行加進去 lines 陣列,最後再一起處理
rl.on("line", function (line) {
  lines.push(line);
});

// 輸入結束,開始針對 lines 做處理
rl.on("close", function () {
  solve(lines);
});

// 上面都不用管,只需要完成這個 function 就好,可以透過 lines[i] 拿取內容
function solve(lines) {
  let temp = lines[0].split(" ");
  let n = Number(temp[0]);
  let m = Number(temp[1]);

  for (let i = n; i <= m; i++) {
    if (isNarcissistic(i)) console.log(i);
  }
}

// 判斷位數
function digitsCount(n) {
  let result = 0;
  if (n === 0) return 1;
  while (n !== 0) {
    n = Math.floor(n / 10);
    result++;
  }
  return result;
}

function isNarcissistic(n) {
  // 幾位數
  let m = n;
  let digits = digitsCount(m);
  let sum = 0;
  while (m !== 0) {
    let num = m % 10;
    sum += num ** digits;
    m = Math.floor(m / 10);
  }
  return sum === n;
}

Q2 解題思路

  1. 先讀取題目提供的參數,n, m,分別設為迴圈的起始及終止條件,迴圈內寫個判斷式,帶入 isNarcissistic(),若為 true,就印出

  2. 先判斷位數才有依據去計算是否符合 isNarcissistic()

  3. 計算位數的部分,設定 result = 0,再來先處理 edge case,0 是一位數,接著就是把這個數不斷除 10 再無條件捨去,每執行一次 result 就加一,直到這個數無法再被 10 除,回傳 result 就能知道是幾位數

  4. isNarcissistic() 部分,先宣告變數 m = n,留著最後檢驗這個數本身是否相等位數相加結果時使用,再來帶入位數運算,得知了是幾位數,先假定 sum = 0,sum 每次會加最後一位數的位數次方,而要得知最後一位數是什麼,就會使用 %,每次 % 10,接著再將此數除 10,再無條件捨去,如此重複,直到 m = 0

  5. 使用三元運算子檢驗 sum 是否等於 n,是,回傳 true,否,回傳 false


Q3 判斷質數

質數的定義為:在大於 1 的自然數中,除了 1 和該數自身以外,無法被其他自然數整除的數。

換句話說,如果一個大於 1 的正整數的因數除了 1 和自己以外就沒有其他的了,那就是質數,以下是前 10 個數字的因數:

1: 1
2: 1, 2
3: 1, 3
4: 1, 2, 4
5: 1, 5
6: 1, 2, 3, 6
7: 1, 7
8: 1, 2, 4, 8
9: 1, 3, 9
10: 1, 2, 5, 10

根據因數可得知,1~10 的質數為:2, 3, 5, 7

現在給你一些數字,請輸出每一個數字是否為質數

Sample Input 1
5
1
2
3
4
5
Sample Output 1
Composite
Prime
Prime
Composite
Prime

Q3 解題

var readline = require("readline");
var rl = readline.createInterface({
  input: process.stdin,
});

var lines = [];

// 讀取到一行,先把這一行加進去 lines 陣列,最後再一起處理
rl.on("line", function (line) {
  lines.push(line);
});

// 輸入結束,開始針對 lines 做處理
rl.on("close", function () {
  solve(lines);
});

// 上面都不用管,只需要完成這個 function 就好,可以透過 lines[i] 拿取內容
function solve(lines) {
  const n = Number(lines[0]);
  const arr = [];
  for (let i = 1; i <= n; i++) {
    arr.push(Number(lines[i]));
  }
  for (let i = 0; i < n; i++) {
    console.log(isPrime(arr[i]) ? "Prime" : "Composite");
  }
}

function isPrime(n) {
  const mid = Math.sqrt(n);
  if (n === 1) return false; // edge case
  for (let i = 2; i <= mid; i++) {
    if (n % i === 0) return false;
  }
  return true;
}

Q3 解題思路

  1. 先將範圍內的數使用陣列處理好,接著只要檢驗這範圍內的數是否符合條件。

  2. 將範圍內的每一個數都使用迴圈去除,只要出現除了 1 與自己以外的數,就回傳 false,否則回傳 true,這邊也運用三元運算子,簡潔許多。

  3. isPrime() 中先將 edge case 獨立出來處理,迴圈再從 2 開始跑,一個一個檢驗,但全部完會耗時太久,這邊做個數學小處理,把要運算的數字都先開根號,因為一個數若有因數,除了 1 與自己,其他必定是對稱的,後面因數會重複,就不用查了。

心得 :

  • isPrime() 內只會回傳布林值,這點提醒自己這時候就要好好遵守,免得之後亂掉,畢竟函式都叫 isPrime() 了。

Q4 判斷迴文

迴文的定義很簡單,就是你把一個字串倒過來以後還是長的跟原字串一樣
舉例來說,aba 倒過來還是 aba,我們就稱 aba 為迴文
abab 倒過來變成 baba,跟原本的字串不一樣,就不是迴文

現在給你一個字串 S,請輸出 S 是否為迴文

一個字串 S, 1 <= length(S) <= 100,

若是迴文請輸出 True,否之則輸出 False

Sample Input 1 
abbbba
Sample Output 1
True
Sample Input 2
ac
Sample Output 1
False

Q3 解題

var readline = require("readline");
var rl = readline.createInterface({
  input: process.stdin,
});

var lines = [];

// 讀取到一行,先把這一行加進去 lines 陣列,最後再一起處理
rl.on("line", function (line) {
  lines.push(line);
});

// 輸入結束,開始針對 lines 做處理
rl.on("close", function () {
  solve(lines);
});

// 上面都不用管,只需要完成這個 function 就好,可以透過 lines[i] 拿取內容
function solve(lines) {
  let str = lines[0]; // abbbba
  console.log(reverse(str) === str ? "True" : "False");
}

function reverse(str) {
  let result = "";
  for (let i = str.length - 1; i >= 0; i--) {
    result += str[i];
  }
  return result;
}

Q4 解題思路

  1. 想到如果要倒著檢查,只要把迴圈的終止條件變成起始,起始變成終止條件,每次減一,就能實現。

  2. 一樣使用空字串,一個字一個字推進去,如果最後推完,長得跟要檢驗的字串一樣,那就回傳 True,否則就是 False。


Q5 聯誼順序比大小

幸好有你的幫忙,小明順利地搶下了聯誼的門票,準備迎接即將到來的聯誼!

班長跟其他幾個康輔社的同學為了這次聯誼準備了許久,希望能帶給對方班級一個良好的印象,也希望能在這次聯誼當中玩得愉快。

而這種聯誼的活動流程,第一個通常都是自我介紹或是玩團康遊戲,像是大家好或者是廣東炒麵之類的。這次的聯誼也不例外,第一個活動就是讓大家輪流自我介紹。

不要小看自我介紹這回事,順序可是很重要的!

若是本身的氣場就很強倒是無所謂,第一個登場可以震驚四方,最後一個登場的話也能夠幫自介環節劃下完美的句點。但如果沒有那麼擅長自我介紹的話,順序就有很大的差別了。

舉例來說,不太擅長說話的小明若是排在了氣場強大的康輔社活動咖同學後面,就會顯得特別弱,因為那個反差太明顯了。但若是小明排在其他也沒那麼會說話的同學後面,就不會顯得特別有問題,這就叫做藏拙,要盡量避免與太厲害的人做比較,否則一開場就輸了。

為了決定自我介紹的順序,班長決定來玩比大小

A 跟 B 兩個人會各自挑好一個數字,挑好以後就不能更改了,接著班長會說要比大還是比小

說完之後兩個人同時講出自己挑好的數字,根據比大或是比小來決定勝負

班長把每一組挑的數字以及比大比小寫在一張紙上,現在請你根據紙上面的輸入,輸出最後比賽的結果

輸入第一行會是一個數字 M,1 <= M <= 50,代表一共有幾組比賽的結果

接著每一行會有三個用空白分隔的數字 A, B, K

A 代表 A 選擇的數字,B 代表 B 選擇的數字,兩者皆保證為正整數
要特別注意的是 A 與 B 可能是很大的數字,但保證長度為 512 個位數以內

K 只會有兩種情況:1 或是 -1,若是 1 代表數字大的獲勝,K 若是 -1 代表數字小的獲勝

針對每一筆輸入,請輸出贏家是誰。

若是 A 贏請輸出 A,B 贏請輸出 B,平手則輸出 DRAW

Sample Input 1
3
1 2 1
1 2 -1
2 2 1
Sample Output 1
B
A
DRAW

Q5 解題

var readline = require("readline");
var rl = readline.createInterface({
  input: process.stdin,
});

var lines = [];

// 讀取到一行,先把這一行加進去 lines 陣列,最後再一起處理
rl.on("line", function (line) {
  lines.push(line);
});

// 輸入結束,開始針對 lines 做處理
rl.on("close", function () {
  solve(lines);
});

// 上面都不用管,只需要完成這個 function 就好,可以透過 lines[i] 拿取內容
function solve(lines) {
  const m = Number(lines[0]);
  for (let i = 1; i <= m; i++) {
    console.log(getWinner(lines[i]));
  }
}

function getWinner(set) {
  const [a, b, result] = set.split(" ");

  if (BigInt(a) === BigInt(b)) {
    return "DRAW";
  } else if (
    (BigInt(a) > BigInt(b) && Number(result) === 1) ||
    (BigInt(a) < BigInt(b) && Number(result) === -1)
  ) {
    return "A";
  } else {
    return "B";
  }
}

Q5 解題思路

  1. 看到題目中「 要特別注意的是 A 與 B 可能是很大的數字,但保證長度為 512 個位數以內 」就知道說這要特別處理,也得知可以使用 BigInt() 這個內建函式

  2. 設定 m 為幾筆資料,使用迴圈,有幾筆資料就跑幾次

  3. 在每筆資料中,都會有三個元素,分別存進 [a, b, result] 中,

  4. 分成兩種情況想

  • A === B 平手
    • 就看分數一樣,就回傳 DRAW
  • A 或 B 贏
    • A 贏:
      1. A > B,且 Number(result) === 1
      2. A < B,且 Number(result) === -1
    • B 贏:
      1. A < B,且 Number(result) === 1
      2. A > B,且 Number(result) === -1

#javascript







Related Posts

[筆記] C++ 01 - 初學者學習

[筆記] C++ 01 - 初學者學習

[Note] JS: Call Stack & Execution Context

[Note] JS: Call Stack & Execution Context

Day05 從 Hash Anchor 看原生 History API (上)

Day05 從 Hash Anchor 看原生 History API (上)


Comments