Если вам интересно, как оценивают программиста на собеседовании в крупных международных компаниях типа Google, Facebook, Ebay, вот несколько примеров заданий, с которыми кандидаты столкиваются при отборе.

Как пройти собеседование на программиста в международную компанию

Во-первых, нужно быть готовым, что презентовать себя нужно будет на английском языке. Безусловно, ИТ компании и платформенный бизнес заинтересован в ваших технических знаниях, поэтому ваши языковые способности менее важны, но чтобы они не помешали справиться с собеседованием, если у вас английский далек от идеального, лучше всего в начале интервью сообщить об этом работодателю и попросить задавать уточняющие вопросы с использованием простых слов и не сложных грамматических конструкций.

Во-вторых, следует подготовиться не только к практическим заданиям по программированию, но и к возможным теоретическим вопросам типа: что значит ХХХ это понятие, что вы понимаете под ХХХ этим термином.

В-третьих, часто процесс собеседования программиста будет включать, помимо тестов, еще и интервью по компетенциям. И для этого не плохо освоить STAR модель ответа.

В-пятых, перед тем как отвечать на вопрос по ожидаемой заработной плате, лучше всего понять какова средняя заработная плата программиста  на этом рынке труда.

Примеры вопросов на собеседовании программиста

Вопрос : Without using the FPU or the / operator, create a function/method in a strongly-typed language of your choice that takes two integers and returns their quotient, exactly mimicking the behavior of the / operator. 

Ожидания от кандидата 

Most people should quickly understand that you can iteratively step up the divisor or step down the dividend until they roughly match, and the number of steps is the quotient. Iterative subtraction is usually preferred, as addition can cause overflow with large numbers. They should be able to identify this is O(n) with respect to the dividend (because in the worse case the divisor is 1). 

Типичные ошибки

  • Many people forget negative numbers and division by zero until they’ve finished.
  • Many people have trouble optimizing from the naive solution, and there are many ways to do this. Depending on the approach they took first, they may choose to see it as performing a binary search through the number line for i such that x =~ iy, or doing a long-division style breakdown like the code sample below.

Off-by-one errors are legion in every solution to this problem, and the candidate can be judged on how well they avoid them, and how elegant their solutions are. For example, finding out your solution always overshoots and just adding a -1 offset in your return statement isn’t as good as fixing the algorithm to remove the overcount. 

Задание на программирование для собеседования

Here’s the naive solution (commented out) and the long-division-style solution in one C function. 

int divide(int x, int y) {

        int quotient = 0;

        unsigned int negative = 0;

        unsigned int offset = 1;

        unsigned int guess;

        if (y == 0) {

                fprintf(stderr, «Divide by zero error\n» );

                exit(EXIT_FAILURE);

        }

        if (x < 0 ^ y < 0) {

                negative = 1;

        }

        x = abs(x);

        y = abs(y);

        /* Naive O(x) solution

        while (x >= y) {

                x -= y;

                quotient++;

        }

        */

        /* Better O(lg x) solution. First we find the greatest number of

         * the form 2ny <= x; from there, we start taking subtracting out

         * factors of 2ny for decrementing n, adding n to the quotient

         * for each removal

         */

        guess = y;

        while (guess << 1 <= x) {

                guess <<= 1;

                offset <<= 1;

        };

        while (guess > 0 && x > 0) {

                if (guess <= x) {

                        x -= guess;

                        quotient |= offset;

                }

                guess >>= 1;

                offset >>= 1;

        }

        return negative ? -quotient : quotient;

}

Here’s the binary-search style solution in Java: 

public static int div(int num, int den) {

 if(den == 0) throw new IllegalArgumentException(«Cannot divide by zero»);

 int isNegative = 1;

 if(num<0) {

  num = -num;

  isNegative = -isNegative;

 }

 if(den<0) {

  den = -den;

  isNegative = -isNegative;

 }

 int upper = num;

 int lower = 0;

 int x = (upper-lower)>>1;

 int rem = num-(den*x);

 while(Math.abs(rem) > den) {

  if(den*x > num) {

    upper = x;

  } else {

    lower = x;

  }

  x = (upper-lower)>>1;

  rem = num-(den*x)

 }

 return isNegative * x;

}

Ожидание от кандидата 

A solid candidate will see the various inflection points around which the function is expected to change: the transition from positive to negative inputs (with zero in between), zero and non-zero remainders, and (if they’re really good) around the MAX_INT and MIN_INT boundaries. 

Should be able to come up with both solutions and their runtimes without much help. Should have complete test coverage intuition. Code should reflect optimal solution, a few off-by-ones are okay as long as hinting gets them resolved. Should not take more than 10-15 minutes. 

Здание 1  для разработчика-программиста для собеседования

What is the output of this perl program? 

 use strict;

 my $list = [«Master», «Code:», «Ninja», «stealthy», «Ninja», «mysterious»];

 my $func = sub { return shift }; #Returns first argument

 sub ninjaize {

   my $list = shift;

   my $function = shift;

   if( scalar @$list == 0 ) { #If list is empty

     $function->( «» ); #Run $function

   }

   else {

     my $first = shift @$list;

     if( $first eq «Ninja» ) {

       ninjaize( $list, $function );

     }

     else {

       ninjaize( $list,

         sub {

           $function->( «Ninja $first » . shift );

         }

       );

     }

   }

 }

 my $result = ninjaize( $list, $func );

 print $result . «\n»;

Здание 2  для разработчика-программиста для собеседования

Write a method that will take 2 version strings like «1.2.3.4» and «5.6» and return > 0 if the first version is greater, 0 if the two are equal, and < 0 if the second version is greater. 

Вариант решения: 

private int compareLayoutVersions(String version1, String version2) {

String[] version1Tokens = version1.split(«\.»);

String[] version2Tokens = version2.split(«\.»);

 

int shortestLength = version1Tokens.length < version2Tokens.length ?

version1Tokens.length : version2Tokens.length;

 

for (int i = 0; i < shortestLength; i++) {

int v1Int = Integer.parseInt(version1Tokens[i]);

int v2Int = Integer.parseInt(version2Tokens[i]);

 

if (v1Int != v2Int)

return v1Int — v2Int;

}

 

//versions are the same up to the length of the shortest version number,

//so return the difference of their lengths

return version1Tokens.length — version2Tokens.length;

}

Пример утончающего вопроса на собеседовании

Assume the input is not good. What checks could you make? 

Вариант правильного ответ: null, non-numeric, multiple dots) 

Здание для интервью с программистом

You need to find as many problems as you can with down mentioned code

/* this code compiles but is buggy */

char *itoa(int num)

{

  char buf[9];

  int digit;

  char c;

  char *p = &buf[0];

  while (num > 0) {

    digit = num % 10;

    c = digit + ‘0’;

    *p = c;

    p++;

    num = num / 10;

  }

  return buf;

}

Правильные ответы 

  • Number comes out reversed 
  • Returns stack-allocated array (‘buf’) (if they know C; if they don’t, give them a pass) 
  • 9 is a magic number, generally bad 
  • 9 is too small to hold a 32-bit int (plus minus sign, plus null terminator) 
  • Doesn’t handle 0 as input 
  • Doesn’t handle negative numbers as input (‘buf’ is too small and code doesn’t insert a minus sign) 
  • Doesn’t null-terminate string 
  • Should let caller pass in buffer (and include size) to avoid memory ownership issues 
  • + ‘0’ trick is potentially ASCII-specific — The function is integer to ASCII. What you’re obviously looking for is not that ‘0’ is ASCII specific, but that itoa is not a very robust function. 
  • Doesn’t handle wide characters — of course it doesn’t, because the signature is char *, not wchar_t *. 
  • Doesn’t handle 64-bit ints (under assumption that original coder’s use of 9 was an attempt to hold a 32-bit int’s worth of digits) 
  • Already are library functions that do this (strtoul, strtol, itoa) — isn’t the point of the exercise to implement a library function? 
  • The variable names suck 

Типичные ошибки при выполнении этого задания 

  • Sometimes candidates get hung up on the + ‘0’ trick (it does actually work, with the caveats below); I’m generally fine with having to explain why it works to them 
  • Candidate never walks thru the code, or picks a really bad example number (such as 1). Indicates sloppy thinking, bad testing techniques. 
  • Candidate notices it doesn’t handle negatives but just assumes it’s «no big deal» («the code’s just supposed to work that way, I guess»). Indicates poor judgment/ownership. 
0.5