Google Interview Question for Software Engineers


Country: United States
Interview Type: Phone Interview




Comment hidden because of low score. Click to expand.
6
of 6 vote

c++, binary search

typedef unsigned short UINT16;

const UINT16 MAX_UINT16 = 65535;

UINT16 withdrawAll() {
	UINT16 money, all;

	money = MAX_UINT16;
	all = 0;
	while (money) {
		if (withdraw(money) == 0) {
			money /= 2;
		} else {
			all += money;
		}
	}

	return all;
}

- kyduke October 14, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

it's correct, but I believe you have to do "money /= 2" anyway;

- koosha.nejad October 14, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

no. He shouldn't, check for the input yourself and see how this works.

- aka October 14, 2015 | Flag
Comment hidden because of low score. Click to expand.
Comment hidden because of low score. Click to expand.
1
of 1 vote

// You have some money in you bank account, the only function to
// withdraw money is `uint_16t withdraw(uint_16t value)`.  If `value`
// is greater than they money you have it returns 0, otherwise it
// withdraws the requested amount and returns the "value".

// Write a function that withdraws all your money.

"use strict";

const withdraw = require('./uint_16t-bank-account-withdraw');

module.exports = function () {
	let money = 0;
	let value = 65535;
	let withdrawal;

	while (value > 0) {
		while (withdrawal = withdraw(value)) {
			money += withdrawal;
		}
		value = Math.floor(value / 2);
	}

	return money;
};

- srterpe October 14, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

I would start from amount = 1 and double the amount each time the transaction is successful.
When we get unsuccessful transaction we divide amount by 2 each time until we reach empty account (basically when we can't withdraw 1):

int amount = 1;

while (account.withdraw(amount) > 0) {
    amount *= 2;
}

while (!(amount == 1 && account.withdraw(amount) == 0)) {
    account.withdraw(amount);

    if (amount > 1) {
        amount /= 2;
    }
}

- damluar October 14, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

uint16 means that you can only withdraw money 65535 each time. But the total money in the bank maybe very very big

- cutail.capricorn October 15, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Weird question. I can smell incremental binary search here but again what he was looking for is something only he will know.

- akaaa October 13, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Could you please elaborate?

- mike.radula October 13, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Basically start from the end to the beginning. Since the api argument is unsigned 16 bit the range is 0 through 65,535 (2^16 - 1). We search from 65535 as below.
1. Lower range = 0, higher range 65535 so we search if the (0+65535)/2 value is 0 or not? Basically just call the api with 65535/2 value.
2. If that is 0 it means the amount in the bank is lesser and consequently otherwise.
3. In case of nonzero value we start taking out money 1 by 1.

unit16 withdraw_total(uint16 value){
int lower = 0; int higher = 65535;
while (lower <= higher) {
int pivot = (lower+higher)/2;
if (withdraw(pivot)) {
while (withdraw(1));
} else {
higher = pivot-1;
}
}
}

- akaaa October 14, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

void allMonies()
{
  int allMonies = 100;
  int counter = 1;
	bool upHill = true;
  while(true)
  {
	  std::cout << allMonies << " " << counter << "\n";
    if(allMonies-counter>0)
		{
		  allMonies -= counter;
			counter *= 2;
		}
		else
		{
      counter /= 2;
			if(!counter)
				break;
		}
  }
}

- Hingle McCringleBerry October 13, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Assuming our maximum amount of money is a 16 bit number, we can incrementally remove from the account the value of each bit in the number if its set, starting from the last bit.

For example, say we have $16972 in the account.

Try 32768 --> too big, nothing removed.
Try 16384 --> take it! (Left is 588)
Try 8192 --> too big, nothing removed.
...
Try 512 --> take it! (Left is 76)
...
Try 64 --> take it! (Left is 12)
..
Try 8 --> take it! (Left is 4)
Try 4 --> take it! (left is 0)
...
Done.

C++

UINT16 withdrawAll()
{
	UINT16 total = 0;
	UINT16 amount = 1 << 15;
	while(amount > 0)
	{
		total += withdraw(amount);
		amount = amount >> 1;
	}
	return total;
}

Complexity: O(16) -> O(1)

- Salsa October 14, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Well, I think this is the correct answer.

- Frank October 15, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

int WithdowAllMoney()
{
uint16_t value = UINT16_MAX;
int moneyTaken = 0;

while (value)
{
uint16_t current = Withdrow(value);
if (current)
{
moneyTaken += current;
}
value = value >> 1;
}

moneyTaken += Withdrow(1);

return moneyTaken;
}

- This solution works for both the total amout is even or odd October 14, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

int WithdowAllMoney()
{
    uint16_t value = UINT16_MAX;
    int moneyTaken = 0;
    while (value)
    {
        uint16_t current = Withdrow(value);
        if (current)
        {
            moneyTaken += current;
        }
        value = value >> 1;
    }
    moneyTaken += Withdrow(1);
    return moneyTaken;
}

- This solution will work for both even and odd money amounts October 14, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

int WithdowAllMoney()
{
    uint16_t value = UINT16_MAX;
    int moneyTaken = 0;

    while (value)
    {
        uint16_t current = Withdrow(value);
        if (current)
        {
            moneyTaken += current;
        }
        value = value >> 1;
    }

    moneyTaken += Withdrow(1);

    return moneyTaken;

}

- Anonymous October 14, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Groovy code with int64 type instead of uint16.

long withdrawAll(long luckyStrike) {
        if (luckyStrike < 1) { return 0 }
        
        int funds = withdraw(luckyStrike)
        if (funds != 0) {
            return funds + withdrawAll(luckyStrike * 2) // care type overflow
        } else {
            return withdrawAll(luckyStrike / 2)
        }   
    }

- nedurno October 15, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

void funny() {
	uint16 value = 65535;
	START:
	while (withdraw(value));
	if (value >>= 1) goto START;	
}

- cutail.capricorn October 15, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

{
void withdrawAll() {
uint16 max = (uint16) ~0;
uint16 withdrawn = 0;
while(max) {
withdrawn += withdraw(max);
max >>= 1;
}
}
}

- PreparingForInterview October 20, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

void withdrawAll() {
uint16 max = (uint16) ~0;
uint16 withdrawn = 0;
while(max) {
withdrawn += withdraw(max);
max >>= 1;
}
}

- osjunkie October 20, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

void withdrawAll() {
  uint16 max = (uint16) ~0;
  uint16 withdrawn = 0;
  while(max) {
    withdrawn += withdraw(max);
    max >>= 1;
  }
}

- osjunkie October 20, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

My C# implementation

public void WithdrawAll()
{
   int maxValue = (int)Math.Pow(2, 16);

   while (Withdraw(maxValue) > 0);

   while (maxValue > 0)
   {
	   Withdraw(maxValue);
	   maxValue /= 2;
   }
}

- hnatsu October 22, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here is C++ version of solution.

Running in log n.

#include<iostream>
#include <cstdint>
using namespace std;

class Account {

public:	
	Account(uint16_t amount):left(amount){}

	uint16_t withdraw(uint16_t value)
	{
		if (left < value)
			return 0;
		else
		{
			left -= value;
			return value;
		}
	}

	uint16_t print()
	{
		cout<<"left = " <<left<<endl;
	}

private:
	uint16_t left;
};


void withdraw_all(uint16_t amount)
{
	uint16_t value = UINT16_MAX;
	Account a(amount);

	uint16_t total = 0;
	int count = 0;

	while (total != amount)
	{
		int returned = a.withdraw(value);
		if (!returned)
			value = value/2;
		else if (returned < value)
		{
			value = (returned > value/2)? returned: value/2;
		} 
		total += returned;
		count++;
	}
	cout <<"withdrew : "<< total<<" from "<<amount <<" in "<<count<< " attampts"<<endl;
}

- hankm2004 November 11, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

In Golang

package main

import (
	"fmt"
)

const MAX_WITHDRAW_AMT = ^uint16(0)

type Account struct {
	balance int
}

func createAccount(balance int) *Account {
	return &Account{balance: balance}
}

func (a *Account) withdraw(amt uint16) uint16 {
	if a.balance >= int(amt) {
		a.balance = a.balance - int(amt)
		return uint16(amt)
	}
	return 0
}

func withdrawAll(a *Account) (int, int) {
	numCalls := 0
	totalAmtWithdrawn := 0
	lastAmtWithdrawn := 0
	withdrawAmt := uint16(MAX_WITHDRAW_AMT)

	for withdrawAmt > 0 {
		lastAmtWithdrawn = int(a.withdraw(withdrawAmt))
		if lastAmtWithdrawn == 0 {
			withdrawAmt = withdrawAmt / 2
		} else {
			totalAmtWithdrawn += lastAmtWithdrawn
		}
		numCalls += 1
	}

	return totalAmtWithdrawn, numCalls
}

func main() {
	var withdrawnAmt int
	var numCallsMade int
	balance := 273717
	account := createAccount(balance)
	withdrawnAmt, numCallsMade = withdrawAll(account)
	fmt.Println(fmt.Sprintf("$%d out of $%d withdrawn on %d calls to withdraw()", balance, withdrawnAmt, numCallsMade))

	balance = 27372
	account = createAccount(balance)
	withdrawnAmt, numCallsMade = withdrawAll(account)
	fmt.Println(fmt.Sprintf("$%d out of $%d withdrawn on %d calls to withdraw()", balance, withdrawnAmt, numCallsMade))

	balance = 283
	account = createAccount(balance)
	withdrawnAmt, numCallsMade = withdrawAll(account)
	fmt.Println(fmt.Sprintf("$%d out of $%d withdrawn on %d calls to withdraw()", balance, withdrawnAmt, numCallsMade))

	balance = int(^uint32(0) >> 1)
	account = createAccount(balance)
	withdrawnAmt, numCallsMade = withdrawAll(account)
	fmt.Println(fmt.Sprintf("$%d out of $%d withdrawn on %d calls to withdraw()", balance, withdrawnAmt, numCallsMade))
}

- Ryan Her February 24, 2016 | Flag Reply


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More