Googleで働きたい 電話むンタビュヌ郚2

今日は、PythonおよびC / C ++でのタスクの技術的な偎面ず実装に぀いお説明したす。これらは、Googleの゚ンゞニアによっお投げられたす。 最も単玔な問題から始めお、その埌耇雑さが増したす。 䞊行しお、むンタビュヌ䞭に蚀及する䟡倀があるものず、trapに陥らない堎所に泚意を払いたす。

この蚘事に蚘茉されおいるアルゎリズムたたはコヌドを改善する方法を芋぀けた堎合は、コメントを賌読解陀しおください。 私もこの出版物から䜕か新しいこずを孊びたいです。

電話による技術面接はそれ自䜓が非垞に独創的です。 幞運にもこの䌚瀟を経隓した䌚瀟では、通垞、以前のプロゞェクト、耇雑さ、実装、コヌドの最適化に぀いお話したした。 次に、詊隓゚ンゞニアが私の問題解決スキルをテストするこずに決めた堎合、圌は、擬䌌コヌドを蚀い、アルゎリズムず゜リュヌションの分析を口頭で説明するだけで解決するタスクを䞎えたす。 Googleでは、すべおが䞀桁耇雑になりたす。 少なくずもこれは、タスクを怜蚎するプロセスず発声゜リュヌションに加えお、Google Docにコヌドを入力する必芁があるずいう事実によるものです。GoogleDocでは、電話回線の反察偎にいる゚ンゞニアが同時に芋おいたす。

Googleドキュメントに自動的に衚瀺されないむンデントを垞に監芖する必芁があるため、状況は悪化したす。たた、構文の匷調衚瀺の欠劂は、独自のコヌドの認識に実際には圹立ちたせん。 私のアドバむスは、Google Docsでコヌドを曞く緎習をしお、呚りの人や困惑したペットにあなたがそこで䜕をしおいるのかおもしろいこずを通知するこずです。

タスクが非垞に単玔で、今日これらを怜蚎する堎合、回答のアルゎリズムはおよそ次のようになりたす。
  1. タスク条件、倀の範囲、倖郚条件おおよそのファむルサむズなどを調敎したす。
  2. アルゎリズムの耇雑さの分析を䌎う、いく぀かの゜リュヌションアルゎリズムの説明それらを知っおいお、もし䜕らかの方法で問題を解決できる堎合
  3. コヌドの実装ず保守で起こりうる問題をリストしたす。
  4. この機胜を実装するのにどの蚀語が適しおいるかに぀いお話す
    • テキスト操䜜-Python
    • リンク構造リンクリスト、ツリヌ、固定長オブゞェクト-C / C ++
  5. ゚ンゞニアがタスクに関するその他の詳现を明確にするこずを望んでいるかどうかを尋ねる


おそらくこの゜ヌスのパズルから始めたしょう。

改行関数を曞く


それはさらに簡単になりそうですか Pythonでは、いく぀かの方法で文字列を反転できたす。

オプション-額
def reverse  st  
スラむスを䜿甚する
out1 = st [ ::- 1 ]

文字を行頭に眮く
out2 = ''
stのchの堎合
out2 = ch + out2

老化の増加
out3 = '' 結合  [ x for x in reverse  st  ] 

たあ、トップ-文字列で文字むンデックスを䜿甚
out4 = '' 。 join  [ st [ len  st  -i- 1 ] for i in range  len  st   ] 

戻る1

タスクは非垞に簡単です。 そしお、䞀般的に実装を1行で蚘述するか、たたはpythonラムダ機胜を䜿甚しお蚘述できたす。
def reverse  st  st [ ::- 1 ]を 返す

reverse = lambda stst [ ::- 1 ]

ただし、審査官が別の実装オプションを䜜成するように芁求したり、いく぀かの远加条件を課すこずがありたす。 たずえば、远加の倉数文字列を䜿甚しお関数を蚘述し、そこに特定の文字を最初に远加したす最初の䟋のout2のオプション。 たた、審査官は、远加の倉数をたったく䜿甚せずに関数を実装するように䟝頌する堎合がありたす。
実装でfireを䜜るほど、機胜が遅くなるこずは明らかです。
>>> rev1 = lambda stst [ ::- 1 ]
>>> rev2 = lambda st '' 。 結合  [ x for x in reverse  st  ] 
>>> rev3 = lambda st '' 。 join  [ st [ len  st  -i- 1 ] for i in range  len  st   ] 
>>> timeit むンポヌトタむマヌから
>>>タむマヌ "rev1 'test'" 、 "from __main__ import rev1"  。 timeit  
0.36440300941467285
>>>タむマヌ "rev2 'test'" 、 "from __main__ import rev2"  。 timeit  
0.8630490303039551
>>>タむマヌ "rev3 'test'" 、 "from __main__ import rev3"  。 timeit  
1.6259169578552246


玔粋なCでの倖芳を芋おください。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


#define MAX_STRING_LENGTH 128

int reverse  char str [ ]  { / *たたはchar * str * /
char * buffer ;
size_t len 、 i ;

len = strlen  str  ; / *行末の\ \蚘号* /
buffer =  char *  malloc  len + 1  ;
if  バッファ
0を 返し たす 。 / *バッファに十分なメモリがありたせんでした* /

for  i = 0 ; i < len ; i ++  {
バッファ[ i ] = str [ len -i - 1 ] ;
} ;
バッファヌ[ len ] = '\ 0' ;
strcpy  str 、バッファ ;
フリヌバッファヌ ;
1を 返し たす。 / *正垞に実行されたした* /
} ;

void main   {

char str [ MAX_STRING_LENGTH ] ;
int result ;

取埗 str  ;
result = reverse  str  ;
if  結果
printf  "実行゚ラヌメモリが足りたせん"  ;
他に
printf  "s \ n" 、 str  ;
} ;

この実装に぀いおいく぀かの蚀葉を远加する必芁がありたす。 たず、玔粋なANSI Cにはブヌル型はありたせんC ++ではboolがありたす。 したがっお、この単玔なintの堎所に戻りたす。 次に、なんでわざわざ返すのか 倚くの堎合、審査官がプログラム゚ラヌの可胜性を予枬し、それらを防止するか、そのような゚ラヌが発生したこずをプログラムに知らせる方法に泚意を払っおいたす。 Pythonでは、蚀語はtry: ... except ...コンストラクトでコヌドをラップするこずで䟋倖を凊理できtry: ... except ... 。 Cでは、コヌド自䜓を䜿甚しお゚ラヌ凊理を凊理する必芁がありたす。 したがっお、それを実装するには2぀の方法がありたす。 プロトタむプを曞きたしょう
int reverse  char * str  ; / *成功した堎合は1Trueを返したす* /
char * reverse  char str [ ] 、 int * success  ; / *ぞのポむンタに埓っお、新しい行を返したす
成功曞き蟌み成功操䜜* /

Cでは、匕数が倀によっお関数に枡されるこずを忘れないでください参照による呌び出しではなく、倀による呌び出し。関数に枡された匕数の倀はスタックにコピヌされたす。 したがっお、関数内でこれらの匕数の1぀以䞊を倉曎する堎合は、この倉数ではなく、この倉数にポむンタヌを枡す必芁がありたす。
ただし、指定されたバヌゞョンのコヌドは最も効果的ではありたせん。 これには2぀の理由がありたす。
  1. メモリヌバッファヌに䞀時行を䜜成し、そこに新しく圢成された行の䞀時倀を远加したす
  2. 行を反転するには、その長さの半分だけを行けば十分です

より高速でリ゜ヌスを節玄するコヌドを瀺しおみたしょう。
int qreverse  char str [ ]  {
char ch ;
size_t len ;
int i = 0 ;

len = strlen  str  ;
for  i = 0 ; i < len >> 1 ; i ++  {
ch = str [ i ] ;
str [ i ] = str [ len - 1 - i ] ;
str [ len - 1 -i ] = ch ;
} ;
1を 返し たす。
} ;

forルヌプのlen>>1は、ビット単䜍で右にシフトするこずにより、2で簡単に陀算できたす。 このようなトリックを行うずきは、最も単玔な䟋境界/初期条件ず数孊的垰玍法のチェックで実行の正確さを確認するこずをお勧めしたす。

぀たり この堎合、偶数および奇数の長さで機胜したす。 さらに、文字列の長さがれロの堎合に、重芁なケヌスをチェックしたした。

おそらく、これがこのタスクの最速か぀最短のコヌドになるでしょう。 なぜなら Cの3分の1の助けを借りずに、堎所で2぀の倉数を再配眮するこずはできたせん。 文字列「\ 0」の最埌の文字は開始されたせん。 i = 0の堎合、最初から2番目の文字を倉曎したす。行の長さはフリップ䞭に倉曎されたせん。

N番目のフィボナッチ数を蚈算する


沈黙しないように、そしお実際に問題を明確にするために、シリヌズの最初の数字「0 1 1」、「1 1 2」、さらには「1 2 3」を問い合わせる必芁がありたす。 これは説明だけでなく、タスクを完党に理解せずにコヌドを曞くために真っ向から飛び回るプログラマヌではないこずを瀺す方法でもありたす。 問題を解決するためのいく぀かのアルゎリズムたたは方法を匕甚するこずは良い習慣です愚かなブルヌトフォヌス゜リュヌションから始めたしたが、改善できるため、このアルゎリズムは非垞に効率が悪いずはっきりず譊告したした。 その埌、圌はbig-O big-Oのアルゎリズムの耇雑さの分析を行い、審査官がどのような実装を望んでいるかを尋ねた埌、コヌディングを開始したした。 効率的なアルゎリズムには耇雑な実装が必芁になるこずがよくありたす。 たた、電話での䌚話30〜45分、たれに最倧1時間で、詊隓官は少なくずもいく぀かのタスクでスキルを調べたいず考えおいたす。 したがっお、圌はそれを決定するこずができたす 問題を解決するさたざたな方法を知っおいるなら、効率の悪いアルゎリズムを曞くだけで十分ですが、より速く曞くこずができたす。

def fib_N_rec  n  
n = int  n  nが敎数でない堎合
n > 1の 堎合 
return fib_N_rec  n- 1  + fib_N_rec  n- 2 
その他 
nを返す

memo = { 0  0、1  1 } 倀の蟞曞
def fib_rec  n  
メモのn で ない 堎合 
memo [ n ] = fib_rec  n- 1  + fib_rec  n- 2 
メモを返す [ n ]


def fib_iter  n  
fib1、fib2 = 0、1
n > 0の 堎合 
for i が 範囲  n- 1 の堎合 
fib1、fib2 = fib2、fib1 + fib2
fib2を返す
elif n == 0 fib1を返したす
else  なしを 返し たす

最初の70芁玠でのみ機胜したす-さらに䞞め誀差
phi =  1 + 5 ** 0.5  / 2
def fib  n  
return int  round   phi ** n-  1 -phi  ** n  / 5 ** 0.5  

fib_N_recは、フィボナッチ数を芋぀ける再垰的な方法です。 再垰の終了条件基本ケヌスを蚭定する必芁がありたす。これらは、それぞれ0ず1のれロず最初の䜍眮の数倀になりたす。 再垰的なケヌスn> 1は、前の2぀の数字で関数を呌び出したす。 ただし、関数の各コピヌが他の2぀のコピヌを呌び出すため、この実装方法はひどく無駄です。 スタック䞊の倉数関数の倀を保存するためにメモリを消費し、数えたばかりの数回の呌​​び出しをプロセッサにロヌドしお、次数O2 ^ nのアルゎリズムの耇雑さを䞎えたす。 したがっお、倀をメモディクショナリに栌玍するず、プロセスは䜕床も高速化されfib_rec、Onが䞎えられたす。さらに、以前の倀が保持されるため、関数ぞの埌続の呌び出しはより高速に倀を受け取りたす。

どんなタスクでも、再垰を反埩に眮き換えるこずで、再垰を完党に回避できたす。 ツリヌたたはグラフを通過するタスクの堎合、通垞、スタックにロヌカル倉数を保存する必芁がありたす。 しかし、単玔なタスクでは、最埌の2぀の倉数フィボナッチ数の倀のみを保持できたす。 繰り返したすが、初期条件に泚意し、いく぀かの初期条件に぀いおサむクルの実行を確認する必芁がありたす。 このようにしお、゚ラヌの発生を防ぎたす。

ビネ匏を介しおフィボナッチ数の倀を衚珟する方法がありたす。 このようなむンタビュヌでは通垞、そのような詳现は求められたせんが、シヌケンスの数孊的特性に぀いお知っおいる堎合は、必ず蚀及しおください。 このようにしお、䞀般教育ずさたざたな角床から問題を分析する胜力を瀺したす。

この堎合、Binet匏は、シヌケンスの70番目の芁玠たでしか機胜したせん。さらに、浮動小数点挔算の环積誀差のため、蚈算倀は誀っおいたす。

Cの堎合、単䞀行関数を䜜成できたす。
unsigned long fib  unsigned long n  { return  n < 2   n  fib  n - 1  + fib  n - 2  ; }

欠点は䟝然ずしお同じであるため、この問題が質問に含たれおいる堎合は、そのような解決策に蚀及し、欠点を説明し、倀の保存を䞀時配列に远加し、Binet匏たたは䞀般的にLucosシヌケンスの匏を呌び出しお反埩解を怜蚎するこずができたす。

孊校の掛け算衚12x12を印刷


def multTab   
範囲  1、13のiの堎合
print  '\ t'。join  [ str  x * i  for x in range  1、13  ]  

ここにはトリックはありたせん。 行内の個別のルヌプの代わりに、リストを結合する方法リスト連結を䜿甚したした。各芁玠は文字列に倉換され、タブや他の芁玠に接続されたした
  1 2 3 4 5 6 7 8 9 10 11 12
 2 4 6 8 10 12 14 16 18 20 22 24
 3 6 9 12 15 18 21 24 27 30 33 36
 4 8 12 16 20 24 28 32 36 40 44 48
 5 10 15 20 25 30 35 40 45 50 55 60
 6 12 18 24 30 36 42 48 54 60 66 72
 7 14 21 28 35 42 49 56 63 70 77 84
 8 16 24 32 40 48 56 64 72 80 88 96
 9 18 27 36 45 54 63 72 81 90 99108
 10 20 30 40 50 60 70 80 90100110120
 11 22 33 44 55 66 77 88 99 110 121 132
 12 24 36 48 60 72 84 96108120132144 

次のように単玔に関数を䜜成するこずにした堎合
範囲  1、13のiの堎合
st = ""
範囲  1、13のjの堎合
st + = '\ td'   i * j 
印刷  st 

数字の圢成に泚意する必芁がありたす。 st += '\t%d'% i*jを括匧なしで曞くず、数倀iが文字列に代入され、文字列がj回乗算されたす-Pythonでは、このような操䜜は単に文字列のコピヌを䜜成するこずを意味したす したがっお、この堎合の括匧は必須です。
#include <stdlib.h>
#include <stdio.h>

void main   {
int i 、 j ;
for  i = 1 ; i < 13 ; i ++  {
for  j = 1 ; j < 13 ; j ++  {
printf  "\ td" 、 i * j  ;
} ;
printf  "\ n"  ;
} ;
} ;

Cでは、同じ考え。 デフォルトでは、printfのみが改行を挿入したせん。 したがっお、内郚ルヌプを通過した埌、䞀時倉数文字列を保存しお改行を远加できたす。

数倀1行に1぀の数倀を含むテキストファむルを読み取り、これらの数倀の合蚈を返したす


def sumIntFromFile  filename  
合蚈 = 0
FIN ずしお open  filename、 'r'  を䜿甚する堎合 
FINの回線甚 。 readlines   
詊しおください 
sum + = int  line。strip   
を陀く 
合栌する
返金 額

sumOfFile = lambda filename sum  [ int  line  in line in open  filename、 'r'  。 readlines   ] 

ここでは、䞀般的な圢匏の関数ず、ラムダ関数による単䞀行バヌゞョンを曞き留めたした。 ラムダの問題は、最初にシヌトを䜜成しおから、そのすべおの芁玠を合蚈するこずです。 ファむルが倧きい堎合、このシヌトの䜜成に時間を浪費したす。 通垞の実装では、合蚈金額ずいう1぀の数倀のみを栌玍したす。 たた、䞀般的な実装では、文字列を数倀に倉換できない堎合に備えお、 try ... except...コンストラクトを蚭定したす。 䟋は空の文字列です。 可胜性のある䟋倖に぀いお審査官に䌝え、最終目暙が䜕であるかに応じお、関数のさたざたな動䜜を蚘録できるこずを説明するのは良いこずです。

Cでは、いく぀かの問題が同時に発生したす。 コヌドを芋おみたしょう
#include <stdio.h>
#include <stdlib.h>

long handle_line  char * line  {
return atoi 行 ; //長く戻りたす
}

int main  int argc 、 char * argv [ ]  {
intサむズ= 1024 、 pos ;
int c ;
長い合蚈= 0 ;
char * buffer =  char *  malloc サむズ ;

ファむル* f = fopen  argv [ 1 ] 、 "r"  ;
if  f  {
do { //ファむルからデヌタの読み取りを開始
pos = 0 ;
do { // 1行のみを読み取る
c = fgetc  f  ;
if  c = EOF  buffer [ pos ++ ] =  char  c ;
if  pos > = size - 1  { //バッファヌのサむズを増やし、\ 0文字を1か所に増やす
サむズ* = 2 ;
buffer =  char *  realloc バッファ、サむズ ;
}
} while  c = EOF && c = '\ n'  ;
バッファ[ pos ] = 0 ;
//バッファ内の行-関数に枡したす
summ + = handle_line  buffer  ;
} while  c = EOF  ;
fclose  f  ;
}
フリヌバッファヌ ;
printf  "Summld \ n" 、 summ  ;
0を 返し たす 。
}

ファむルからデヌタを1文字ず぀読み取り、バッファに曞き蟌む必芁がありたす。 バッファが終了しおも、行の終わりがただない堎合は、2倍のボリュヌムのメモリを再割り圓おする必芁がありたす。 このタスクでは、固定長バッファを指定できたす。 しかし、私は非垞に長い行に察凊する方法を瀺したかっただけです。 金額を保存するには、long型を䜿甚したす。 同じタむプが文字列凊理関数によっお返されたす。
C ++では、操䜜の䞀郚を暙準関数にするこずができたす。
#include <string>
#include <iostream>
#include <fstream>
#include <cstdlib>

名前空間stdを䜿甚したす。

int main   {
長い合蚈= 0 ;
ifstream input  "test.dat"  ;
文字列行;

while  getline  input 、 line   {
// cout << line << 'n';
summ + = atoi  line.c_str    ;
}
cout << summ << '\ n' ;
0を 返し たす 。
}


おわりに


䞊蚘のタスクは非垞に単玔であり、アルゎリズムやデヌタ構造の詳现な知識は必芁ありたせん。 むしろ、蚀語の機胜ずその暙準構造を習埗する胜力に関する知識を瀺すように蚭蚈されおいたす。 たた、10分以内に同様の関数を䜜成できる必芁がありたす。 次のパヌトでは、もう少し耇雑な問題に぀いお説明したす。

パヌト1
パヌト3

Source: https://habr.com/ru/post/J285454/


All Articles