Open Lichen5221 opened 3 years ago
陣列總和虛擬碼:
let sum = 0
for (i from 0 to n-1) do
sum += arr[i]
end for
print sum
轉成程式碼:
let sum = 0
for (let i = 0; i < n; i++) { //也可以寫成 for (let i = 0; i <= n - 1; i++)
sum += arr[i]
}
console.log(sum)
找最大值虛擬碼:
let max = arr[0]
for (i from 0 to n-1) do
if (arr[i] > max) do
max = arr[i]
end if
end for
print max
轉成程式碼:
let max = arr[0] // 設定成非空陣列
for (var i = 1; i < n; i++) {
if (arr[i] > max) {
max = arr[i]
}
}
console.log(max)
注意輸入範圍,如果給予空陣列,前面需要再寫一個關於出現空陣列要做的事情。
避免雙層迴圈。
虛擬碼試寫:
let number = n
for ( i from 1 to n ) do
if ( i 為質數 ) do
print 'prime'
else do
print 'composite'
end if
end for
老師寫的:
for (i from 0 to n-1) do
if (arr[i] 是質數 ) do
print 'Prime'
else
print 'Composite'
end if
end for
差異:老師使用陣列,且從 0 開始到 n - 1 。因為是有 n 個數字,不是給定數字 n 。
翻成程式碼:
for (let i = 0; i < n; i++) {
if (arr[i] 為質數) { // 變成:if (isPrime(arr[i]))
console.log('Prime')
} else {
console.log('Composite')
}
}
function isPrime(n) { //不知道的地方就 function
if ( n === 1 ) return false // 1 當作特殊 case 處理
for (let i = 2; i < n; i++) {
if (n % i === 0 ) { //只要有能整除的數就不是質數
return false
}
}
return true //放在 for 迴圈外,因為放在迴圈內會變成找到一個沒整除就視為質數,但所謂質數應該是全部都不能整除(除了自己跟 1 ),所以要放在 for 迴圈外。
}
拔掉 function 的話:
for (let i = 0; i < n; i++) {
let isPrime = true //把函式拿掉,維持主邏輯不變。
if (arr[i] === 1) { // edge case 也要加入
isPrime = false
}
for (let j = 2; j < arr[i]; j++) { //加上判斷質數程式碼
if (arr[i] % j === 0) {
isPrime = false
break
}
}
if (isPrime) {
console.log('Prime')
} else {
console.log('Composite')
}
}
加 function 加爆:
for (let i = 0; i < n; i++) {
handleNumber(arr[i])
}
function handleNumber(n) {
if (isPrime(n)) {
console.log('Prime')
} else {
console.log('Composite')
}
}
function isPrime(n) {
if (n === 1) return false
for (j = 2; j < n; j++) {
if (n % j === 0) {
return false
}
}
return true
}
在進行練習前,確保程式可以運行,但發現還要自定義陣列太累了,所以寫了一個前置 function ,只要給定 n 就好,自己有透過終端機的 node 執行確認 ok ,供參:
var n = 10
var arr = arr(n)
function arr(n){
var ar = [ ]
for(var i = 1; i <= n; i++) {
ar.push(i)
}
return ar
}
for (let i = 0; i < n; i++) {
let isPrime = true //把函式拿掉,維持主邏輯不變。
if (arr[i] === 1) { // edge case 也要加入
isPrime = false
}
for (let j = 2; j < arr[i]; j++) { //加上判斷質數程式碼
if (arr[i] % j === 0) {
isPrime = false
break
}
}
if (isPrime) {
console.log('Prime')
} else {
console.log('Composite')
}
}
正式練習程式腦:
for (let i = 0; i < n; i++) {
let isPrime = true //把函式拿掉,維持主邏輯不變。
if (arr[i] === 1) { // edge case 也要加入
isPrime = false
}
for (let j = 2; j < arr[i]; j++) { //加上判斷質數程式碼
if (arr[i] % j === 0) {
isPrime = false
break
}
}
if (isPrime = true) {
console.log('Prime')
} else {
console.log('Composite')
}
}
難的解不出來,先寫簡化版。
自己試寫:
function star(n){
for (var i = 1; i < n; i++){
console.log('*'.repeat(i))
}
}
star(6)
在 node 上可以執行也正確,但不知道為什麼在 LIOJ 上是錯誤答案,是因為 LIOJ 不能用 repeat 的語法嗎?
老師解法:
for (let i = 1; i <= N; i++) {
printStar(i)
}
function printStar(n) {
let s = ' '
for (let i = 1; i <=n; i++) {
s += '*'
}
console.log(s)
}
不是,結果是我少加一個等於⋯⋯好蠢⋯⋯但我也順便學了不用 repeat 怎麼跑 repeat 。
內建函式使用這三個都可以解決。
規律要馬跟 n 有關,要馬跟 i 有關。
看出規律:
- 一共有 n 層
- 第 i 層會有 2i - 1 個星星 //自己看出的規律是 1 + 2*(i - 1)
- 星星會置中
- 需要 n - i 個空白 //沒有想出來,一直糾結兩邊都有空白。
老師解答:
for (let i = 1; i <= n; i++) {
printLayer(i, n) //要把第 i 層跟全部有幾層一起傳進去
}
function printLayer(i, n) {
let str = repeat(' ', n - i) + repeat('*', 2*i - 1) // JS 可直接加,其他程式不一定。
console.log(str)
}
function repeat(str, n) { //輔助的函式
let s = ' '
for (let i = 1; i <= n; i++) {
s += str
}
return s
}
自己試寫:
for (i = 1; i <= 9; i++) {
for (j = 1; j <= 9; j++ ){
console.log(String(i),'*',String(j), '=', i*j)
}
}
寫出來能成功跑出九九乘法表自己都感到訝異XD
老師解答:
function printTable(k) {
for (let i = 1; i <= 9; i++) {
console.log(k + '*' + i + '=' + k*i)
}
}
for (let k = 1; k <= 9; k++) {
printTable(k)
}
老師雙重 for 迴圈寫法:
for (let k = 1; k <= 9; k++) {
for (let i = 1; i <= 9; i++) {
console.log(k + '*' + i + '=' + k*i)
}
}
差異:我還把 i j 轉成字串了XD
雙重迴圈的部分可能因為前面自己練習寫過判斷質數、第二週作業六的部分,所以九九乘法表的雙重迴圈還算好理解!
還以為是指把 1 - 100 的平方都印出來,原來是指 1 - 100 裡面是平方的數字(開根號為整數)。
自己試寫:
for (var i = 1; i <= 100; i++){
if (Math.sqrt(i) % 1 === 0) {
console.log(i)
}
}
老師解法一:
for (let i = 1; i <= 100; i++) {
if (isSquare(i)) {
console.log(i)
}
}
function isSquare(n) {
let root = Math.floor(Math.sqrt(n))
return root * root === n
}
差異:我覺得我的比較簡單。
老師解法二: 找出自己相乘小於 100 的數即 1 - 100 間的平方數。
let i = 1
while(i * i <= 100) {
console.log(i * i)
i++
}
自己試寫: 把 for 迴圈拆成樹葉和樹幹。
var n = 3
function repeat(str, n) {
let s = ''
for(let i = 1; i <= n; i++) {
s += str
}
return s
}
for (var i = 1; i <= n; i++) {
let leaves = repeat(' ', n - i) + repeat('*', 2 * i - 1)
console.log(leaves)
}
for (var i = 1; i <= n - 1; i++) {
let trunk = repeat(' ', n - 1) + repeat('|', 1)
console.log(trunk)
}
自己試寫: 就只是把九九乘法表的 9 換成 n 跟 m。
function ms(n, m){
for (i = 1; i <= n; i++) {
for (j = 1; j <= m; j++ ){
console.log(String(i),'*',String(j), '=', i*j)
}
}
}
ms(9, 5)
奇怪欸我自己執行 node 答案就是對的,上去 LIOJ 就不對。
莫名其妙欸就一定要用 + 連接這些東西,我就喜歡用逗號分隔不行嗎?呈現出來明明就沒差。
我竟然寫出來了!
var lines = [1, 10000]
var n = lines[0]
var m = lines[1]
for (var i = n; i <= m; i++) {
var arr = String(i).split('')
let ans = 0
for (var k = 0; k < arr.length; k++) {
ans += Number(arr[k])**arr.length
}
if (i === ans) {
console.log(i)
}
}
不敢置信 XD 現在只差在怎麼搞定那個以空白分隔兩個正整數的部分,在 LIOJ上要怎麼寫才行⋯⋯
結果我還是參考老師的方式寫前面的 n m 設置。我的寫法跟老師的寫法好像都不一樣,晚點回到家再來看老師怎麼寫。
寫程式最後一步:看清題目
弄清題意,翻成白話文。
考驗程式能力前,先考驗閱讀能力。
LOIJ 1008:幾個水桶
最重的小事:輸入範圍
因為需求不同,範圍會改變。不同範圍有不同限制。
基本限制:空間、時間、型態。
空間限制:
時間限制: 初學題目來說不重要,但講到 big O 就很重要。
寫出基本,才能增加效率。連基本都沒有,就不用講求效率了。
型態限制:
LIOJ 1004 聯誼順序比大小
!解題前一定要先搞清楚範圍!
輸入與輸出方式
輸出方式:
Project 3 介紹
用白話文改寫題目,提出解題中有可能碰到的問題或需要注意的地方。
LIOJ 1010:靈魂伴侶
給定兩個數字 n ,介於 1 - 2147483647 之間,相同的話輸出 yes,不同的話輸出 no 。
即判斷兩數是否相同,範圍 OK 。
LIOJ 1015:音速小子
給定數字 n , 介於 1 - 100000 之間,求出其 * 340 的結果。
即簡單運算,範圍 OK。
LIOJ 1017:貪婪的小偷
我的理解:最大值取 C 次。
老師講解:取價值最高的 C 項物品,範圍 OK。