
30 Câu Phỏng Vấn Kỹ Thuật Với Javascript (Phần 1)
Hôm nay chúng ta sẽ điểm qua top 30 câu hỏi phỏng vấn javascript. Trong phần 1 này, mình sẽ giới thiệu tới các bạn 10 câu hỏi đầu tiên trong loạt bài “Top 30 câu hỏi phỏng vấn Javascript thường gặp”
I. Câu hỏi:
1. Viết function đảo ngược một chuỗi cho trước
Đây có thể nói là câu hỏi huyền thoại, bất cứ coder nào cũng phải ít nhất một lần nghe đến nó, vậy thì ở javascript chúng ta làm như thế nào?
Javascript không có lớp String Builder như các ngôn ngữ khác (Java, C#,..), việc chúng ta có thể làm ở đây là tạo 1 mảng, sau đó push các kí tự từ chuỗi gốc vào, sau đó dùng Array.join để tạo thành chuỗi mới, nói thì dài dòng, mời các bạn xem code phía dưới
function reverseString(s) {
// Create the result list
const result = [];
// Start from the end of the string and iterate towards the start
for (let i = s.length-1; i >= 0; i -= 1) {
// Push the current char in the list
result.push(s[i]);
}
// Combine the result in a string
return result.join('');
}
// Examples
console.log(reverseString(""))
console.log(reverseString("abc"))
console.log(reverseString("aaabbbcccd"))
2. Viết một function filter number từ một mảng.
Với câu hỏi này, chúng ta sẽ phải filter trong mảng và remove tất cả những gì không phải là số. Nhưng làm thế nào để chúng ta có thể check được một phần tử có phải là số hay không?. Well, trong trường hợp này thì chúng ta có thể sử dụng typeof
để check
typeof 1 // number
nhưng đôi khi đời không như mơ, interviewer nói rằng “1” cũng được xem là số, trong trường hợp này khi chúng ta dùng typeof thì kết quả sẽ như bên dưới:
typeof "1" // string
Kết quả trả về sẽ không giống như chúng ta mong muốn. Solution ở đây là dùng isNaN
function:
Cho dù là vậy, nếu chúng ta để ý (hoặc là interviewer khó tính :<), chúng ta sẽ gặp phải 2 trường hợp như bên dưới khi dùng isNaN
isNaN('') //false
isNaN(true) //false
Vì vậy chúng ta phải tiếp tục kiểm tra xem, phần tử có là boolean hay là một string rỗng hay không:
function isBoolean(value) {
return typeof value === 'boolean';
}
function isEmptyString(value) {
return typeof value === 'string' && value.trim().length === 0;
}
Và dưới đây là một câu trả lời hoàn chỉnh:
function filterNumbers(arr) {
// Create the result list
const result = arr.filter(function(value, i) {
// Filter based on the rules for checking the input is number
if (isNaN(value) || isBoolean(value) || isEmptyString(value)) {
return false;
}
return true;
});
// Return numbers only list
return result;
}
function isBoolean(value) {
return typeof value === 'boolean';
}
function isEmptyString(value) {
return typeof value === 'string' && value.trim().length === 0;
}
console.log(filterNumbers([1, "2", " ", NaN, Number.POSITIVE_INFINITY, 66, "ab1", false]))
3. Viết function tìm kiếm phần tử trong một mảng
Đây là ví dụ điển hình của thuật toán “tìm kiếm tuyến tính”, tên tiếng Anh là “Linear Search”. Để giải quyết bàn toán này chúng ta phải duyệt qua tất cả các phần tử trong mảng để lấy ra được phần tử chúng ta cần tìm:
function linearSearch(arr, x) {
let lo = 0;
let hi = arr.length-1;
// Iterate from start till end of list
while (lo <= hi) {
// If item was found then return index
if (arr[lo] === x) {
return lo;
} else {
lo += 1
}
}
// Return -1 to denote the item was not found
return -1;
}
let arr = [1,3,5,7,9,11,14,18,22];
console.info("Item was found at index: " + linearSearch(arr, 22));
4. Viết function mô tả được closure trong js.
Nếu bạn chưa biết về closure trong javascript là gì thì có thể tham khảo ở đây
Dưới đây là một ví dụ đơn giản về closure:
function multiplier(first) {
let a = first;
return function(b) {
return a * b;
};
}
let multiplyBy2 = multiplier(2);
console.info(multiplyBy2(4));
console.info(multiplyBy2(5));
Và sau ví dụ này, bạn cũng có thể phải giải thích clousure là gì đấy nhé 😀
5. Promise là gì, viết function trả về promise.
Để có cái nhìn chi tiết hơn về promise, các bạn có thể xem thêm ở đây
Đây là một ví dụ cơ bản về Promise:
const resultPromise = function(idea) {
return new Promise(function(resolve, reject) {
if (idea.isGood) {
resolve(idea);
} else {
reject({
idea: idea,
reason: "Not Realistic"
});
}
});
};
resultPromise({idea: "Make Gold from Iron", isGood: false})
.then(function() {
console.info("I'm Rich!")
}, function(err) {
console.info("Rejected as: " + err.reason);
});
6. Write a function that flattens a list of items (cái này dịch ra tiếng Việt hông có hay cho lắm).
Đây cũng là một câu hỏi điển hình. Các bạn có thể hiểu được câu hỏi này qua ví dụ sau:
Cho một mảng là: [1, [2,3, [4]]]
thì sẽ trả về một mảng là [1,2,3,4].
Tức là mảng trả về chỉ gồm “1-level”
Để có thể làm được điều này, quan trọng nhất là chúng ta phải xác định được mảng đó có bao nhiêu mảng con. Bên dưới là câu trả lời cho bài toán này:
function flatten(arr=[]) {
// Create the result list;
let result = [];
for (let item of arr) {
// If item is an array we concat the contents
if (Array.isArray(item)) {
result = result.concat(flatten(item));
} else {
result = result.concat(item);
}
}
return result;
}
console.info(flatten([[1, 2, [3]], 4]));
7. Viết function tìm kiếm phần tử trong một mảng – dùng thuật toán tìm kiếm nhị phân
Cũng là bài toán tìm kiếm phần tử trong mảng, nhưng lần này chúng ta không dùng linear search nữa mà là dùng binary search. Cách implement thuật toán này bạn có thể xem code mẫu bên dưới:
function binarySearch(arr, x) {
let lo = 0;
let hi = arr.length-1;
while (lo <= hi) {
// Find mid element
let m = Math.floor((lo + hi) / 2);
// Check if equal to target
if (arr[m] === x) {
return m;
// Reduce array search space by half
} else if (arr[m] < x) {
lo = m + 1;
} else {
hi = m - 1;
}
}
// Item not found
return -1;
}
let arr = [1,3,5,7,9,11,14,18,22];
console.info(console.info("Item was found at index: " + binarySearch(arr, 22)));
8. Viết function nhận đầu vào là 2 số a, b và trả về thương số và số dư của phép chia a,b.
Với bài toán này, chúng ta cần phải trả về 2 kết quả dưới
a / b
và a % b
.
function divMod(a, b) {
// Be careful for division by zero
if (b !== 0 ) {
return [a / b, a % b];
}
return [0, 0];
}
console.info(divMod(16, 5));
console.info(divMod(20, 0));
9. Tính tổng các số fibonacci của một số N.
Trong dãy fibonacci, mỗi số đều là tổng của 2 số đứng trước nó.
Ví dụ: 0, 1, 1 , 2, 3, 5 ,8 ...
Chúng ta có thể giải bài toán này bằng cách dùng đệ quy hoặc vòng lặp while loop. Với đệ quy, chúng ta có thể làm như này:
function fib(n) {
if (n === 0) {
return 0;
} else if (n === 1) {
return 1;
} else {
return fib(n-1) + fib(n-2);
}
}
Ở trên vẫn chưa phải là lời giải tối ưu nhất, và nếu được interviewer hỏi, bạn có thể sửa lại như bên dưới:
function memo(func) {
let cache = {};
return function (x) {
if (x in cache) return cache[x];
return cache[x] = func(x);
};
};
let fib = memo(function(n) {
if (n === 0) {
return 0;
} else if (n === 1) {
return 1;
} else {
return fib(n-1) + fib(n-2);
}
});
console.info(fib(20))
10. Viết function, nhận đầu vào là một chuỗi, trả về một “map” tần suất các kí tự xuất hiện trong chuỗi.
Để tính toán tần suất, chúng ta sẽ dùng hash-table. Thông thường, để giải bài toán này, chúng ta sẽ dùng object-mapping với key là các kí tự trong chuỗi và value là tần suất xuất hiện các kí tự đó, hoặc là dùng javascript Map
Dưới đây là solution cho bài toán này:
function computeFrequency(s) {
// Create the freq hashtable
const freqTable = new Map();
// for each char in the string
for (ch of s) {
// Check if we have seen it already
if (!freqTable.has(ch)) {
freqTable.set(ch, 1);
} else {
// Just increase the existing entry
freqTable.set(ch, freqTable.get(ch) + 1);
}
}
// Return result
return freqTable;
}
console.info(computeFrequency("abrakatabra"));
II. Lời kết
Vậy là chúng ta đã đi qua 10 câu hỏi trong series “30 câu hỏi phỏng vấn javascript”, mong rằng qua series này các bạn sẽ trang bị cho mình một vốn kiến thức javascript để có thể chinh chiến trên mọi mặt trận và không gặp bất cứ khó khăn gì khi đối mặt với các interviewer trong các vòng phỏng vấn.
Hẹn gặp lại các bạn trong P2.
Đừng quên 5* cho mình nhé.
Post Comment