0%

題目

1
2
3
4
5
Input
["ParkingSystem", "addCar", "addCar", "addCar", "addCar"]
[[1, 1, 0], [1], [2], [3], [1]]
Output
[null, true, true, false, false]

解法思維

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var ParkingSystem = function(big, medium, small) {
this.big=big
this.medium=medium
this.small=small
};

ParkingSystem.prototype.addCar = function(carType) {
if(carType==1){
this.big-=1
return this.big>=0
}else if(carType==2){
this.medium-=1
return this.medium>=0
}else if(carType==3){
this.small-=1
return this.small>=0
}
}
1
2
3
4
5
6
var ParkingSystem = function(big, medium, small) {
this.remainingSpaces = [big, medium, small];
};
ParkingSystem.prototype.addCar = function(carType) {
return (this.remainingSpaces[carType - 1]--) > 0
};

1
<canvas id="cvs" width="800" height="600" style="border: 1px solid #000000;"></canvas>

基本用法

綁定 canvas

1
2
3
4
5
const cvs=document.querySelector('#cvs')
// 宣告 Canvas Content Object
getContext() 2d webgl
// 2D 畫面 3D 畫面
const ctx= cvs.getContext('2d')

Fill 填滿

1
2
3
4
5
6
// 填滿顏色
ctx.fillStyle="red"
// 透明度 1 為不透明 0 為完全透明
ctx.globalAlpha=0.5
// fillRect(X,Y,weight,height)
ctx.fillRect(50,50,100,100)

Stroke 描邊

1
2
3
4
// 描邊顏色
ctx.strokeStyle='blue'
// strokeRect(X,Y,weight,height)
ctx.strokeRect(100,100,100,100)

Path 路徑

1
2
3
4
5
6
7
8
9
10
// 開啟路徑
ctx.beginPath()
// 移動到當前所在位置 moveTo(X,Y)
ctx.moveTo(300,300)
// 與設定座標畫一直線 lineTo(X,Y)
ctx.lineTo(400,500)
// 關閉路徑
ctx.closePath()
// 選擇顯現方式 stoke() fill()
ctx.stroke()

繪製多邊形

1
2
3
4
5
6
ctx.beginPath()
ctx.moveTo(300,300)
ctx.lineTo(100,500)
ctx.lineTo(500,500)
ctx.closePath()
ctx.fill()

影像處理、濾鏡

影像處理

1
2
3
4
5
6
let img=new Image() 
img.src='../head.png'
img.onload=function () { // 註冊 load 事件,圖片載入完成後,入完成後,才做繪製
// drawImage(img,X,Y,width,height)
ctx.drawImage(img,0,0,cvs.width,cvs.height)
}

濾鏡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Html
<button onclick="invertColor()">影像反轉</button>
<canvas id="cvs" width="800" height="600" style="border: 1px solid #000000;"></canvas>
// JavaScript
function invertColor(){
let pixels=ctx.getImageData(0,0,cvs.width,cvs.height)
//一個像素佔據 4 個資料 (bytes) 。 r,g,b,a(範圍 0 ~ 255)
let pixelsData=pixels.data
for (let i = 0; i < pixelsData.length; i+=4) {
pixelsData[i]=255-pixelsData[i]
pixelsData[i+1]=255-pixelsData[i+1]
pixelsData[i+2]=255-pixelsData[i+2]

}
ctx.putImageData(pixels,0,0)
}

檔案輸入、輸出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Html

<input type="file" onchange="loadFile(this)">
<button onclick="saveFile()">儲存檔案</button>
<a href="" id="download"></a>
<canvas id="cvs" width="800" height="600" style="border: 1px solid #000000;"></canvas>

// JavaScript

function loadFile(input){
// 抓取 input files
let files=input.files[0]
// 把 files 轉成網址
let url=URL.createObjectURL(files)
let img=new Image()
img.src=url
img.onload=function () {
ctx.drawImage(img,0,0,cvs.width,cvs.height)
}
}

function saveFile() {
const link=document.querySelector('#download')
// a 連結下載格式
link.download='image.jpg'
// canvas 輸出格式
link.href=cvs.toDataURL('image/jpeg')
link.click()
}

畫線

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
let painting=false
// 按下滑鼠代表開始畫畫
cvs.addEventListener('mousedown',startPosition)
// 放下滑鼠代表完成畫畫
cvs.addEventListener('mouseup',finishedPosition)
// 滑鼠移動代表正在畫畫
cvs.addEventListener('mousemove',draw)


function startPosition() {
painting=true
}
function finishedPosition(e) {
painting=false
ctx.beginPath()
}
function draw(e) {
// 如果正在畫畫就 return
if(!painting)return
if(stroke && !eraser){
ctx.lineWidth=size
ctx.strokeStyle=color
ctx.lineCap='round'
ctx.lineTo(e.clientX,e.clientY)
ctx.stroke()
ctx.beginPath()
ctx.moveTo(e.clientX,e.clientY)
}else if(!stroke && eraser){
ctx.lineWidth=size
ctx.strokeStyle='#E8E8E8'
ctx.lineCap='round'
ctx.lineTo(e.clientX,e.clientY)
ctx.stroke()
ctx.beginPath()
ctx.moveTo(e.clientX,e.clientY)
}
}

Undo、Redo

創建一個物件,每次畫完就擷取圖片存在物件裡,物件[步驟]讀取畫面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
let restore_array=[]
let step=-1


function finishedPosition(e) {
painting=false
ctx.beginPath()
console.log(e.type)
if(e.type!='mousedown'){
restore_array.push(ctx.getImageData(0,0,cvs.width,cvs.height))
step++
}
if(restore_array.length>0){
console.log(1)
domUndo.classList.add('btn-active')
}else{
domUndo.classList.remove('btn-active')
}
}

function undo(e) {
e.preventDefault()
if(step<=0){
allClear()
domUndo.classList.remove('btn-active')
}else{
console.log(restore_array)
domUndo.classList.add('btn-active')
step--
ctx.putImageData(restore_array[step],0,0)
}
if(step<restore_array.length&&step>=0){
domRedo.classList.add('btn-active')
}else{
domRedo.classList.remove('btn-active')
}
}
function redo(e) {
e.preventDefault()
console.log(step)
if(step==restore_array.length||step<0){
return
}else if(step<restore_array.length){
step++
ctx.putImageData(restore_array[step],0,0)
}
}

題目

1
2
Input: jewels = "aA", stones = "aAAbbbb"
Output: 3

解法思維

跑迴圈比對

1
2
3
4
5
6
7
8
9
10
11
12
var numJewelsInStones = function(jewels, stones) {
let c=0
for (const jew of jewels) {
for (const ston of stones) {
if(jew==ston){
c++
}
}

}
return c
};

先解構再用filter()篩選

1
2
3
4
var numJewelsInStones = function(jewels, stones) {
let s=[...stones].filter((item)=>jewels.includes(item))
return s.length
};

題目

1
2
3
Input: nums = [1,2,3,1,1,3]
Output: 4
Explanation: There are 4 good pairs (0,3), (0,4), (3,4), (2,5) 0-indexed.

解法思維

想到跑雙迴圈判斷

1
2
3
4
5
6
7
8
9
10
11
12
var numIdenticalPairs = function(nums) {
let counter = 0;
for (let i = 0; i < nums.length; i++) {
for (let j = i+1; j < nums.length; j++) {
if(nums[i]===nums[j]){
counter++
}

}
}
return counter
};

利用for of

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var numIdenticalPairs = function(nums) {
let obj = {};
let counter = 0;

for (val of nums) {
if (obj[val]) {
counter += obj[val];
obj[val]++;
} else {
obj[val] = 1;
}
}
console.log(obj);
return counter;
};

JS-for…in與for…of的差別

題目

1
2
3
Input: address = "1.1.1.1"
Output: "1[.]1[.]1[.]1"

解法思維

將字串分割split() 再加回去join()

1
var defangIPaddr = address=> { return address.split('.').join('[.]')};

splice()

1
var defangIPaddr = address=> {return address.replace(/[.]/g,'[.]')};

題目

1
2
3
4
Input: nums = [2,5,1,3,4,7], n = 3
Output: [2,3,5,4,1,7]
Explanation: Since x1=2, x2=5, x3=1, y1=3, y2=4, y3=7
then the answer is [2,3,5,4,1,7].

解法思維

跑迴圈再依序加入

1
2
3
4
5
6
7
var shuffle = function(nums, n) {
let result=[]
for (let i = 0; i < n; i++) {
result.push(nums[i],nums[i+n]);
}
return result
};

先用slice()拆分物件,再跑迴圈,依序加回去

1
2
3
4
5
6
7
8
9
var shuffle = function(nums, n) {
let result=[]
let x =nums.slice(0,n)
let y=nums.slice(n)
for (let i = 0; i < x.length; i++) {
result.push(x[i],y[i]);
}
return result
};

slice()

1
2
3
arr.slice()
arr.slice(begin)
arr.slice(begin, end)
1
2
3
4
5
6
7
8
9
10

let fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'];
let fruit1 = fruits.slice(1);
let fruit2 = fruits.slice(1, 3);
let fruit3 = fruits.slice(-3);

// fruits contains ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango']
// fruit1 contains ['Orange', 'Lemon', 'Apple', 'Mango']
// fruit2 contains ['Orange', 'Lemon']
// fruit3 contains ["Lemon", "Apple", "Mango"]

題目

1
2
3
4
5
6
7
8
Input: candies = [2,3,5,1,3], extraCandies = 3
Output: [true,true,true,false,true]
Explanation:
Kid 1 has 2 candies and if he or she receives all extra candies (3) will have 5 candies --- the greatest number of candies among the kids.
Kid 2 has 3 candies and if he or she receives at least 2 extra candies will have the greatest number of candies among the kids.
Kid 3 has 5 candies and this is already the greatest number of candies among the kids.
Kid 4 has 1 candy and even if he or she receives all extra candies will only have 4 candies.
Kid 5 has 3 candies and if he or she receives at least 2 extra candies will have the greatest number of candies among the kids.

解法思維

map()相加,在跟 Math.max()比較,回傳結果

1
var kidsWithCandies = (candies, extraCandies) =>candies.map(v => (v + extraCandies) >= Math.max(...candies));

題目

1
2
3
4
5
6
Input: accounts = [[1,2,3],[3,2,1]]
Output: 6
Explanation:
1st customer has wealth = 1 + 2 + 3 = 6
2nd customer has wealth = 3 + 2 + 1 = 6
Both customers are considered the richest with a wealth of 6 each, so return 6.

解法思維

foreach()取出物件,再用reduce()計算,最後用 Math.max()抓出最大值

1
2
3
4
5
6
7
8
9
10
var maximumWealth = function(accounts) {
let sum=[]
accounts.forEach(item => {
item.reduce(function (a, b) {
sum.push(a+b)
return a + b
}, 0);
});
return Math.max(...sum)
};

題目

1
2
3
Input: nums = [1,2,3,4]
Output: [1,3,6,10]
Explanation: Running sum is obtained as follows: [1, 1+2, 1+2+3, 1+2+3+4].

解法思維

foreach()依序相加,再回傳

1
2
3
4
5
6
7
8
9
var runningSum = function(nums) {
let total=[]
let sum=0
nums.forEach(item => {
sum+=item
total.push(sum)
});
return total
};

reduce()依序相加,再回傳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* @param {number[]} nums
* @return {number[]}
*/
var runningSum = function(nums) {
/*
The current array index is increamented by the accumlator which is the new value of arr[i]

Example trace:

input:
[1,2,3,4]

acc i arr return value
0 0 1,2,3,4 0 + 1 = 1
1 1 1,2,3,4 1 + 2 = 3
3 2 1,3,3,4 3 + 3 = 6
end => 6 3 1,3,6,4 6 + 4 = 10
10 4 1,3,6,10

*/
nums.reduce((acc, _, i, arr) => arr[i] += acc )
return nums

};

題目

1
2
3
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums[1] == 9, we return [0, 1].

解法思維

剛開始是想跑兩個迴圈,跑完再判斷相加是否等於目標值

1
2
3
4
5
6
7
8
9
var twoSum = function(nums, target) {
for (let i = 0; i < nums.length; i++) {
for (let j = 1; j < nums.length; j++) {
if(nums[i]+nums[j]==target){
return [i,j]
}
}
}
};

別人的想法:跑迴圈,在判斷目標數值與迴圈數值相減,是否有在obj={}

1
2
3
4
5
6
7
8
9
10
11
12
13
var twoSum = function(nums, target) {
//object for storing value and their index
const obj = {};
const len = nums.length;
for( let i=0; i< len; i++ ){
//if target - current value in array exist in obj then that's what we need
if( target - nums[i] in obj ){
return [ obj[ target - nums[i] ], i ];
}
//if target - current value doesn't exist in obj then push the value in obj
obj[ nums[i] ] = i;
}
};