Tác giả: Nguyễn RR Thành Trung
Bạn đã bao giờ bước vào một cuộc phỏng vấn mà không biết phải chuẩn bị gì? Bạn đã bao giờ phỏng vấn xong, nghĩ mình trả lời cũng ổn, nhưng vẫn bị đánh trượt? Trong bài viết này, mình muốn chia sẻ về việc phỏng vấn từ góc nhìn của người phía bên kia chiến tuyến.
Ở Garena Singapore, mình được làm nhiệm vụ phỏng vấn các ứng viên nộp đơn vào vị trí Software Engineer.
Quy trình phỏng vấn của Garena có thể nói là khá đơn giản, sau khi hồ sơ qua được vòng duyệt hồ sơ, thí sinh phải trải qua:
Chú ý rằng trong bài viết này, mình chỉ chia sẻ quan điểm của cá nhân mình về việc phỏng vấn. Nó không phản ánh quan điểm của Garena và có thể không đúng nếu bạn phỏng vấn Garena với một người phỏng vấn khác.
Theo quan điểm của mình, một cuộc phỏng vấn là một cuộc tìm hiểu lẫn nhau của ứng viên và công ty:
Như đã nói ở trên, nội dung phỏng vấn gồm rất nhiều phần:
Tùy theo người phỏng vấn, họ sẽ hỏi các phần ở các độ sâu khác nhau, tuy nhiên thuật toán và kĩ năng code thường là phần quan trọng nhất. Cá nhân mình thì chỉ giỏi về thuật toán và code, nên mình thường chỉ hỏi tập trung vào 2 phần đó, và các phần khác mình thường hỏi khá đơn giản.
Thông thường, với câu hỏi về thuật toán, mình sẽ nhìn vào Resume của ứng viên để chọn câu hỏi. Thường sau khi nhìn hồ sơ mình chia thành 3 nhóm:
Với 3 nhóm, độ khó câu hỏi cũng như yêu cầu của mình sẽ khác nhau.
Với nhóm 1 và 2 (và thỉnh thoảng là nhóm 3), mình hỏi cùng 1 câu hỏi như sau:
Cho mảng A gồm N phần tử và một số nguyên S. Đếm số cặp chỉ số (i, j) mà A(i) + A(j) = S Ví dụ: A = [1, 5, 2, 4, 3] S = 6 –> code của bạn cần trả lại 2
Sau khi nghe xong câu hỏi thì thường bạn sẽ phải nói cho mình cách làm, sau khi mình thấy hợp lý thì bạn có thể bắt đầu code. Mình chọn câu hỏi này vì nó có nhiều cách làm:
1. Cách $O(N^2)$
Cách hiển nhiên nhất $O(N^2)$: Dùng 2 vòng for
để đếm. Đây là cách cơ bản nhất và ứng viên buộc phải trả lời được. Cài đặt cũng rất đơn giản như sau:
int result = 0;
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if (A[i] + A[j] == S)
result += 1;
Chú ý vòng for
bên trong chạy từ i+1
để tránh đếm trùng. Điều này tưởng như rất đơn giản nhưng nhiều thí sinh thuộc nhóm 1 không làm được (các bạn thường for
từ 0 và không xử lý được khi thấy đếm bị trùng).
2. Cách $O(N * logN)$
Một cách cài đặt "trâu bò" hơn là $O(N * logN)$:
Sắp xếp lại rồi với mỗi $A_i$, chặt nhị phân để đếm số lượng giá trị $j$. Cách này có nhược điểm là dễ bị đếm trùng. Để khắc phục thì có 2 cách:
Mình nhận thấy 1 số bạn trong nhóm 2 đi theo hướng này, nhưng mình không đánh giá cao vì nó phức tạp hơn cách 3 ở dưới. Nhưng tất nhiên nếu bạn cài đặt tốt và đơn giản thì không sao cả.
Khi ứng viên trả lời theo hướng này, thường (tùy theo cảm hứng của mình lúc phỏng vấn), mình có thể hỏi thêm:
sort
nào?sort
nào?sort
với độ phức tạp $O(N * logN)$ không?3. Cách $O(N)$
Cách "chuẩn" $O(N)$ là sử dụng hash table hoặc map
trong C++ để lưu lại các phần tử của dãy, vừa lưu vừa đếm:
map<int,int> count;
int result = 0;
for (int i = 0; i < n; i++) {
result += count[S - a[i]];
count[a[i]] += 1;
}
Thường nếu các bạn chỉ nghĩ ra cách 1, sau khi bạn cài đặt xong, nếu thấy còn đủ thời gian mình sẽ gợi ý để làm được cách này.
Nếu ứng viên trả lời theo hướng này, mình cũng có thể hỏi thêm:
Khi ứng viên trả lời, mình đánh giá theo nhiều tiêu chí:
Mình dùng đi dùng lại 1 câu hỏi vì như vậy mình sẽ nắm được rất rõ các cách trả lời khác nhau và các lỗi bạn đã gặp phải. Tuy nhiên tùy ngẫu hứng mình sẽ có thể hỏi thêm các chi tiết khác nhau, ví dụ:
sort
, bạn có biết sort
của C++ dùng thuật toán gì không? Nếu dùng vector
, bạn có biết độ phức tạp mỗi thao tác là bao nhiêu không?range
và xrange
không? Bạn có biết nó khác gì nhau không?Thường những câu hỏi này mình hỏi khá ngẫu hứng và trong trường hợp không trả lời được, bạn cũng không cần lo lắng.
Với nhóm 3, thường mình sẽ hỏi câu như sau:
Cho 1 xâu S. Đếm số substring của S là Palindrome
Bài này cũng có 2 cách làm chính với độ phức tạp $O(N^2)$:
Thỉnh thoảng, với nhóm 1 hoặc 2, nếu bạn trả lời câu trước quá kém và mình thấy còn thời gian, mình sẽ cho "gỡ gạc" bằng câu này, tuy nhiên mình chỉ yêu cầu làm cách duyệt toàn bộ với độ phức tạp $O(N^3)$ là đủ.
Đánh giá của mình cũng dựa trên những tiêu chí như phần trên.
Phần này mình thường không hỏi nhiều. Mình thường sẽ bắt đầu bằng câu hỏi:
Thread và Process giống và khác nhau thế nào?
Sau đó, tùy theo cách bạn trả lời hoặc tâm trạng của mình lúc đó, mình có thể hỏi thêm 1 số phần khác như:
Mình không giỏi về hệ điều hành nên thường yêu cầu không cao. Bạn trả lời được những ý cơ bản là đạt yêu cầu của mình.
Phần này mình cũng thường không hỏi nhiều. Mình thường bắt đầu bằng câu hỏi:
UDP và TCP khác nhau thế nào?
Sau đó, mình có thể hỏi thêm 1 số phần khác như:
Mình không giỏi về phần nên thường yêu cầu không cao. Bạn trả lời được những ý cơ bản là đạt yêu cầu của mình.
Ở Garena mình được đánh giá là một trong những người phỏng vấn khó tính nhất. Với những người khó tính như mình, có một số lỗi mà bạn cần tránh trong suốt quá trình phỏng vấn:
git commit
là gì.Thông thường, các công ty sẽ hạn chế đưa ra Feedback đối với thí sinh. Thông thường nếu bạn hỏi sẽ chỉ nhận được những câu trả lời chung chung và hầu hết công ty sẽ không đưa ra lý do chính xác khiến bạn bị đánh trượt. Lý do là để bảo vệ công ty: