Google Interview Question for SDE-2s


Country: India
Interview Type: Written Test




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

C#
complete class with Test() method testing '+' operator

class ThousandDigitNumber
{
    const int MaxSize = 1000; //Some max number of digits
    const int Base = 10;

    List<byte> value = new List<byte>();
    Boolean positive = true;//sign

    public static ThousandDigitNumber operator+ (ThousandDigitNumber num1, ThousandDigitNumber num2)
    {
        ThousandDigitNumber result = new ThousandDigitNumber();

        if (! num1.positive)
        {

            if (num2.positive) //same as num2 - num1
            {
                return num2 - num1;
            }
            else //two negative numbers
            {
                result.positive = false;
            }
        }
        else if (!num2.positive) //same as num1 - num2
        {
            return num1 - num2;
        }

        ThousandDigitNumber min, max;

        int minSize = num1.value.Count();
        if (minSize > num2.value.Count())
        {
            min = num2;
            max = num1;
            minSize = num2.value.Count();
        }
        else
        {
            min = num1;
            max = num2;
        }
        int maxSize = max.value.Count();

        int carry = 0;
        int sum;

        for (int i = 0; i < minSize; i++)
        {
                sum = min.value[i] + max.value[i] + carry;
                carry = sum/Base;
                result.value.Add((Byte) (sum % Base));
        }
                        
        for (int j = minSize; j < maxSize; j++)
        {
                sum = max.value[j] + carry;
                carry = sum / Base;
                result.value.Add((Byte)(sum % Base));
        }

        if (carry == 1)
        {
            if (result.value.Count() < MaxSize)
            {
                result.value.Add((Byte) carry);
            }
            else
            {
                throw new OverflowException();
            }
        }

        return result;
    }

    public static ThousandDigitNumber operator-(ThousandDigitNumber num1, ThousandDigitNumber num2)
    {
        ThousandDigitNumber result = new ThousandDigitNumber();

        if (!num1.positive)
        {
            if (num2.positive) //(-a) - b -> -(a+b)
            {
                ThousandDigitNumber num3 = new ThousandDigitNumber(num1);
                num3.positive = true;//change the sign
                result = num3 + num1;
                result.positive = false;
                return result;
            }
            else //(-a) - (-b) = -(b - a)
            {
                //swap
                ThousandDigitNumber tmp = num1;
                num2 = num1;
                num1 = num2;
                result.positive = false;
            }
        }
        else if (! num2.positive) // a - (-b) -> a + b
        {
            return num1 + num2;
        }

        //now do num1 - num2
        // if num2 > num1, then result = - (num2 - num1)
        ThousandDigitNumber min, max;

        int minSize = num2.value.Count();

        if (minSize > num1.value.Count())
        {//num1 < num2
            min = num1;
            max = num2;
            minSize = num1.value.Count();
            result.positive = !result.positive;
        }
        else if (minSize < num1.value.Count())
        {//num1 > num2
            min = num2;
            max = num1;
        }
        else //minsize = maxsize
        {
            min = num2;
            max = num1;
            //find which one is really larger and which one is smaller
            //starting from msd to lsd
            for(int i = minSize - 1; i >=0; i--)
            {
                if (num1.value[i] < num2.value[i]) //num1 < num2
                {
                    min = num1;
                    max = num2;
                    result.positive = !result.positive;
                    break;
                }
            }
        }
        int maxSize = max.value.Count();

        int sub;
        int carry = 0;
        //Now, finally we can do max - min
        for (int i = 0; i < minSize; i++ )
        {
            sub = max.value[i] - min.value[i] - carry;
            if (sub < 0)
            {
                sub = Base + sub; //get complement
                carry = 1;
            }
            else
            {
                carry = 0;
            }
            result.value.Add((Byte) sub);
        }

        for (int j = minSize; j < maxSize; j++)
        {
            sub = max.value[j] - carry; //this cannot overflow so no testing
            if (sub < 0)
            {
                sub = Base + sub; //get complement
                carry = 1;
            }
            else
            {
                carry = 0;
            }
            result.value.Add((Byte) sub);
        }

        result.RemoveLeadingZeros();
        return result;
    }

    private void RemoveLeadingZeros()
    {
        for (int i = value.Count() - 1; i >= 0; i--)
        {
            if (value[i] != 0)
            {
                break;
            }
            else
            {
                value.RemoveAt(i);
            }
        }
    }
    public ThousandDigitNumber()
    { }
    //copy constructor
    public ThousandDigitNumber(ThousandDigitNumber num)
    {
        this.value.AddRange(num.value);
        this.positive = num.positive;
    }

    public ThousandDigitNumber(String num)
    {
        Parse(num);
    }

    private void Print()
    {
        if (!positive)
            Console.Write("-");

        if (value.Count == 0)
        {
            Console.Write("0");
        }

        for (int i = value.Count() - 1; i >= 0; i--)
        {
            Console.Write(value[i]);
        }
    }

    private void Parse(String num)
    {
        if (num != null && num.Length > 0)
        {
            int i = 0;
            if (num[0] == '-')
            {
                this.positive = false;
                i++;
            }
            else if (num[0] == '+')
            {
                i++;
            }

            if (num.Length > MaxSize)
            {
                throw new OverflowException();
            }

            for (int j = num.Length - 1; j >= i; j--)
            {
                value.Add(Byte.Parse(num[j].ToString()));
            }
        }
    }
    public void Test()
    {
        ThousandDigitNumber t1 = new ThousandDigitNumber("89");

        ThousandDigitNumber t2 = new ThousandDigitNumber("999911");
        t1.Print();
        Console.Write(" + ");
        t2.Print();
        Console.Write(" = ");
        ThousandDigitNumber t3 = t2 + t1;
        t3.Print();
        Console.WriteLine();
    }
}

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

Good approach. I would also propose to use List<ulong> rather than List<byte> and Base = 10^19. This way you need only 64 bits to represent pointer in a list and 64 bits to represent 18-digits number = 128 bytes in total.
For List<byte> and Base = 10 you need: (64 bytes (to represent a pointer) + 1 byte to represent 1-digit number) * 18 = 65 * 18 = 1170 bytes to represent 18-digits number.

- Alex M. April 15, 2017 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Approach is
1. Create a class "VeryLongINT"
2. it contains two fields 1. vector<int> 2. bool Sign (sign TRUE for +ve num, FALSE for -ve)
3. add operator methods to perform Addition and subtraction
4. whiel performing addition and subtraction operation we need to take care, "VeryLongINT" object sign.
5. E.g (obj1) + (-obj2), here I perform subtraction.
(obj1) + (-obj2) = obj1 - obj2
6. (-obj1) -(obj2) = -(obj+obj2);

// GoogleVeryLongInteger.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;

class VeryLongINT
{
public:
	VeryLongINT()
	{
	}

	VeryLongINT(const vector<int> &vect, bool sign1 = true)
	{
		number = vect;
		sign = sign1;
	}

	VeryLongINT(const VeryLongINT &obj)
	{
		number = obj.number;
		sign = obj.sign;
	}
	void printNum()
	{
		cout << endl;
		char ch = sign == true ? '+' : '-';
		cout << ch;
		for (int i = 0; i < number.size(); i++)
			cout << number[i];
	}
	friend VeryLongINT operator+(VeryLongINT obj1, const VeryLongINT obj2);
	friend VeryLongINT operator-(VeryLongINT obj1, const VeryLongINT obj2);
	friend VeryLongINT operator-(VeryLongINT obj);
	friend bool absCompare(const VeryLongINT &obj1, const VeryLongINT &obj2);
private:
	vector<int> number;
	bool sign; // sign flag TRUE if num is +ve otherwise false
};

// Add operator
VeryLongINT operator+(VeryLongINT obj1, VeryLongINT obj2)
{
	if (obj1.sign == obj2.sign)
	{
		VeryLongINT result;
		int i = obj1.number.size() - 1;
		int j = obj2.number.size() - 1;
		int carry = 0;
		while (i >= 0 || j >= 0 || carry == 1)
		{
			int temp = 0;
			if (i >= 0)
			{
				temp += obj1.number[i--];
			}
			if (j >= 0)
			{
				temp += obj2.number[j--];
			}
			temp += carry;
			result.number.push_back(temp % 10);
			carry = temp / 10;
		}
		reverse(result.number.begin(), result.number.end());
		result.sign = obj1.sign;
		return result;
	}
	else
	{
		// if obj1.sign is -ve
		if (obj1.sign == false)
		{
			obj1.sign = true;
			return obj2 - obj1;
		}
		// if obj2.sign is -ve
		else
		{
			obj2.sign = true;
			return obj1 - obj2;
		}
	}
}

//Subtract operator
VeryLongINT operator-(VeryLongINT obj1, VeryLongINT obj2)
{
	if (obj1.sign == obj2.sign)
	{
		if (absCompare(obj1, obj2))
		{
			VeryLongINT result;
			int i = obj1.number.size() - 1;
			int j = obj2.number.size() - 1;
			int carry = 0;
			while (i >= 0 || j >= 0 || carry == 1)
			{
				if (j >= 0)
				{
					int temp = obj1.number[i] - carry - obj2.number[j];
					carry = temp < 0;
					if (carry)
					{
						temp += 10;
					}
					result.number.push_back(temp);
					i--;
					j--;
				}
				else
				{
					if (carry == 1)
					{
						int temp = -carry;
						carry = 0;
						temp += obj1.number[i];
						if (temp > 0 || i > 0)
						{
							result.number.push_back(temp);
						}
						i--;
					}
					while (i >= 0)
					{
						result.number.push_back(obj1.number[i]);
						i--;
					}
				}
			}
			reverse(result.number.begin(), result.number.end());
			result.sign = obj1.sign;
			return result;
		}
		else {
			return -(obj2 - obj1);
		}
	}
	else
	{
		return obj1 + (-obj2);
	}
}

// unary operator
VeryLongINT operator-(VeryLongINT obj)
{
	// just negate sign
	obj.sign = obj.sign ? false : true;
	return obj;
}

bool absCompare(const VeryLongINT &obj1, const VeryLongINT &obj2)
{
	if (obj1.number.size() > obj2.number.size())
	{
		return true;
	}
	else if (obj1.number.size() < obj2.number.size())
	{
		return false;
	}
	else
	{
		for (int i = 0; i < obj1.number.size(); i++)
		{
			if (obj1.number[i] == obj2.number[i])
				continue;
			return obj1.number[i] > obj2.number[i] ? 1 : 0;
		}
		return true;
	}
}

int main()
{

	vector<int> a(3, 2);
	vector<int> b(2, 1);
	VeryLongINT *obj1 = new VeryLongINT(a,false);
	VeryLongINT *obj2 = new VeryLongINT(b);
	VeryLongINT result = *obj1 + *obj2;
	obj1->printNum();
	obj2->printNum();
	cout << "\nAddition" << endl;
	result.printNum();
	free(obj1);
	free(obj2);
	cout << "\n*********" << endl;
	vector<int> c(3, 2);
	vector<int> d(4, 1);
	VeryLongINT *obj3 = new VeryLongINT(c);
	VeryLongINT *obj4 = new VeryLongINT(d);
	result = *obj3 - *obj4;
	obj3->printNum();
	obj4->printNum();
	cout << "\nSubtraction" << endl;
	result.printNum();
	free(obj3);
	free(obj4);
	cout << "\n*********" << endl;
	getchar();
	return 0;
}

- siva.sai.2020 October 18, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

I think, the main concern would be the following:
1. Verify the numbers the correct, since we don't want very long ints to be 1223567-789..
2. After add or sub considering the sign, there can be leading 0, one needs to remove those and have the sign appropriately.
3. Overflow or underflow will depend on the max length allowed. The max length also needs to be set while creating the number.
4. "0" value number should ideally have no sign, but keeping it + will help.

Also, in the above solution, it would be better to have vector<unsigned> instead of vector<int>.

- Anon October 18, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Anon, Thanks

- siva.sai.2020 October 21, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here is the C++ version of solution. Using vector<int> to store the numbers.

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

class BigInt{

public:
	vector<int> numbers;
	bool sign;

	BigInt():sign(true)
	{
		sign = true;
	}

	BigInt(string value)
	{
		for (int i = 0 ; i < value.length(); i++ )
		{
			if (i == 0 && value[i] == '-')
				sign = false;
			else {
				numbers.push_back('0'+value[i]);
			}
		}
	}

	BigInt(const BigInt& b)
	{
		this->sign = b.sign;
		this->numbers = b.numbers;
	}

	BigInt& operator=(const BigInt& r)
	{
		sign = r.sign;
		numbers = r.numbers;
		return *this;
	}

	BigInt(vector<int> number, bool s)
	{
		numbers = number;
		sign = s;
	}

	BigInt operator+ (BigInt& r)
	{
		BigInt result;
		int lpos = (*this).numbers.size() -1;
		int rpos = r.numbers.size() -1;
		int carry = 0;

		if (this->sign && r.sign)
			result.sign = true;
		else if (!this->sign && !r.sign)
			result.sign = false;
		else if (!this->sign)
			return r - *this;
		else 
			return (*this) - r;

		while (rpos >= 0 || lpos >= 0)
		{
			int left = (lpos >= 0)? this->numbers[lpos] :  0;
			int right = (rpos >= 0)? r.numbers[rpos]  :  0; 		
			int sum = left + right + carry;
			carry = sum/10;
			result.numbers.insert(result.numbers.begin(), sum%10);
			lpos--;
			rpos--;
		}

		if (carry > 0)
			result.numbers.insert(result.numbers.begin(), carry);
		return result;
	}

	BigInt operator- (BigInt& r)
	{
		BigInt result;
		int carry = 0;

		if (!this->sign && !r.sign)
		{
			r.sign = true;
			return r - *this;
		}else if (!this->sign && r.sign)		
		{
			r.sign = false;
			return (*this)+r;
		}
		else if (this->sign && !r.sign)
		{
			r.sign = true;
			return (*this)+r;
		}		
		BigInt* left = this;
		BigInt* right = &r;

		int c = compare(*this, r);
		if (c == 0)
		{
			result.numbers.push_back(0);
			return result;
		} else if (c == -1)
		{
			left = &r;
			result.sign = false;
			right = this;
		}
		int lpos = left->numbers.size() -1;
		int rpos = right->numbers.size() -1;

		int diff = 0;
		while (rpos >= 0 || lpos >= 0)
		{
			int lvalue = (lpos >= 0)? left->numbers[lpos] :  0;
			int rvalue = (rpos >= 0)? right->numbers[rpos]  :  0; 		

			if (lvalue == 0 && lpos < 0)
			{
				diff = rvalue + carry;
				if (result.sign) result.sign = false;
				carry = 0;
			}else if (lvalue < (rvalue + carry))
			{
				diff = 10+lvalue - rvalue - carry;
				carry = 1;
			} else {
				diff = lvalue  - rvalue - carry;
			}
			result.numbers.insert(result.numbers.begin() ,diff);	
			lpos--;
			rpos--;
		}
		return result;

	}

	int compare(BigInt & l, BigInt & r)
	{
		if (l.numbers.size() == r.numbers.size())
		{
			for ( int i = 0; i < l.numbers.size(); i++)
			{
				if (l.numbers[i] != r.numbers[i])
					return (l.numbers[i] > r.numbers[i])? 1 : -1;			
			}		
		}
		else
			return (l.numbers.size() > r.numbers.size())? 1 : -1;

		return 0;
	}

	string to_string()
	{
		string result;
		if (!this->sign)
			result.push_back('-');

		for (int i = 0; i < this->numbers.size(); i++)
			result.push_back('0'+this->numbers[i]);
		return result;
	}
};


int main()
{
	vector<int> int1;
	int1.push_back(1);
	int1.push_back(9);
	int1.push_back(2);
	int1.push_back(8);
	BigInt bint1(int1, true);
	
	vector<int> int2;
	int2.push_back(2);
	int2.push_back(0);
	int2.push_back(0);
	int2.push_back(0);
	BigInt bint2(int2, true);
	
	BigInt bint3;
	bint3 = (bint1 + bint2);
	cout << "result = " << bint3.to_string().c_str()<<endl;

	BigInt bint4 = (bint2 - bint1);
	cout << "result 2 = " << bint4.to_string().c_str()<<endl;

	BigInt bint5 = (bint1 - bint2);
	cout << "result 2 = " << bint5.to_string().c_str()<<endl;

	vector<int> int6;
	int6.push_back(5);
	int6.push_back(2);
	BigInt bint6(int6, true);

	BigInt bint7 = bint6 - bint2;

	cout <<" "<<bint6.to_string().c_str()<<" - " << bint2.to_string().c_str()<<" = " << bint7.to_string().c_str()<<endl;

	BigInt answer  = BigInt("675") - BigInt("899");
	cout <<"675 - 899 =" <<answer.to_string().c_str() <<endl;

	BigInt answer2  = BigInt("675") - BigInt("-899");
	cout <<"675 - (-899) =" <<answer2.to_string().c_str() <<endl;
	return 1;
}

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

My implementation uses a maximum of 104 integer to store the integer data

using System;
using System.Collections.Generic;
using System.Text;

class VBI : IComparable<VBI>
{
    const ulong MAXDP1 = 0x100000000;
    const uint MAXD = 0xFFFFFFFF;
    const int MAXN = 104;
    int sign = 0;
    List<uint> data = new List<uint>();
    public VBI()
    {
    }
    public VBI(VBI v, int s)
    {
        this.sign = v.sign * s;
        this.data.AddRange(v.data);
    }
    public int CompareTo(VBI x)
    {
        return CompareTo(x, true);
    }
    public int CompareTo(VBI x, bool considerSign)
    {
        if (x == null)
            return 1;
        int ret;
        if (considerSign)
        {
            ret = this.sign.CompareTo(x.sign);
            if (ret != 0)
                return ret;
            if (this.sign == 0)
                return 0;

        }
        ret = this.data.Count.CompareTo(x.data.Count);
        if (ret != 0)
            return ret * x.sign;
        for (int i = data.Count - 1; i >= 0; i--)
        {
            ret = this.data[i].CompareTo(x.data[i]);
            if (ret != 0)
                return ret * x.sign;
        }
        return 0;
    }
    public static VBI _add(VBI a, VBI b, int sign)
    {
        VBI c = new VBI();
        if (a.data.Count < b.data.Count)
        {
            VBI t = a;
            a = b;
            b = t;
        }
        int na = a.data.Count;
        int nb = b.data.Count;
        bool carry = false;
        for (int i = 0; i < nb; i++)
        {
            ulong dc = (ulong)a.data[i] + (ulong)b.data[i];
            if (carry)
                dc++;
            if (dc > MAXD)
            {
                carry = true;
                c.data.Add((uint)dc & MAXD);
            }
            else
            {
                carry = false;
                c.data.Add((uint)dc);
            }

        }
        for (int i = nb; i < na; i++)
        {
            if (carry)
            {
                ulong dc = (ulong)a.data[i] + (ulong)1;
                if (dc > MAXD)
                    c.data.Add((uint)(dc & MAXD));
                else
                {
                    carry = false;
                    c.data.Add((uint)dc);
                }
            }
            else
                c.data.Add(a.data[i]);
        }
        if (carry)
        {
            if (c.data.Count == MAXN)
                throw new Exception(sign == 1 ? "Overflow" : "Underflow");
            c.data.Add(1);
        }
        c.sign = sign;
        return c;
    }
    public static VBI _sub(VBI a, VBI b, int sign)
    {
        VBI c = new VBI();
        switch (a.CompareTo(b, false))
        {
            case 0:
                return c;
            case -1:
                VBI t = a;
                a = b;
                b = t;
                sign = -sign;
                break;
        }
        int na = a.data.Count;
        int nb = b.data.Count;
        bool carry = false;
        int zs = -1;
        for (int i = 0; i < nb; i++)
        {
            ulong dc;
            ulong da = a.data[i];
            ulong db = b.data[i];
            if (carry) db++;
            if (da >= db)
            {
                carry = false;
                dc = da - db;
            }
            else
            {
                carry = true;
                dc = (MAXDP1 + da) - db;
            }
            if (dc == 0)
            {
                if (zs == -1)
                    zs = i;
            }
            else
            {
                if (zs != -1)
                {
                    for (int j = zs; j < i; j++)
                        c.data.Add(0);
                    zs = -1;
                }
                c.data.Add((uint)dc);
            }
        }
        for (int i = nb; i < na; i++)
        {
            uint dc;
            if (carry)
            {
                if (a.data[i] == 0)
                    dc = MAXD;
                else
                {
                    dc = a.data[i] - 1;
                    carry = false;
                }
            }
            else
                dc = a.data[i];
            if (dc == 0)
            {
                if (zs == -1) zs = -1;
            }
            else
            {
                if (zs != -1)
                {
                    for (int j = zs; j < i; j++)
                        c.data.Add(0);
                    zs = -1;
                }
                c.data.Add(dc);
            }
        }
        c.sign = sign;
        return c;
    }
    public VBI(uint val, int sign)
    {
        if (val == 0)
            return;
        this.sign = sign;
        this.data.Add(val);
    }
    public static VBI operator +(VBI x, VBI y)
    {
        if (x.sign == 0)
            return new VBI(y, 1);
        if (y.sign == 0)
            return new VBI(x, 1);
        if (x.sign == y.sign)
            return _add(x, y, x.sign);
        return _sub(x, y, x.sign);
    }
    public static VBI operator -(VBI x, VBI y)
    {
        if (x.sign == 0)
            return new VBI(y, -1);
        if (y.sign == 0)
            return new VBI(x, 1);
        if (x.sign == y.sign)
            return _sub(x, y, x.sign);
        return _add(x, y, x.sign);
    }
    public static VBI parse(string s)
    {

        VBI r = new VBI();
        if (string.IsNullOrEmpty(s))
            return r;
        int sign = 1;
        if (s[0] == '-')
        {
            sign = -1;
            s = s.Substring(1);
        }
        if (s.Length > 1000)
            throw new Exception("String too long");
        for (int i = 0; i < s.Length; i++)
        {
            int d = s[i] - '0';
            if (d < 0 || d > 9)
                throw new Exception("Invalid string");
            if (r.sign != 0)
            {
                uint carry = 0;
                for (int j = 0; j < r.data.Count; j++)
                {
                    ulong p = (r.data[j]) * ((ulong)10) + ((ulong)carry);
                    r.data[j] = (uint)(p & MAXD);
                    carry = (uint)(p >> 32);
                }
                if (carry != 0)
                    r.data.Add(carry);
            }
            r = r + new VBI((uint)d, 1);
        }
        r.sign = r.data.Count == 0 ? 0 : sign;
        return r;
    }
    public override string ToString()
    {
        if (sign == 0)
            return "0";
        StringBuilder ret = new StringBuilder();
        VBI c = new VBI(this, 1);
        while (c.data.Count > 0)
        {
            uint carry = 0;
            int trailingZeroCount = 0;
            bool trailingZeros = true;
            for (int i = c.data.Count - 1; i >= 0; i--)
            {
                ulong d = (ulong)((ulong)carry << 32) + (ulong)c.data[i];
                uint q = (uint)(d / 10);
                c.data[i] = q;
                if (q == 0)
                {
                    if (trailingZeros)
                        trailingZeroCount++;
                }
                else
                    if (trailingZeros)
                        trailingZeros = false;
                carry = (uint)(d % 10);
            }
            ret.Insert(0, carry);
            for (int i = 0; i < trailingZeroCount; i++)
                c.data.RemoveAt(c.data.Count - 1);
        }
        if (sign < 0)
            ret.Insert(0, "-");
        return ret.ToString();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(VBI.parse("99999999999999999999") + VBI.parse("1"));
        Console.WriteLine(VBI.parse("100000") - VBI.parse("1"));
    }
}

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

That's 10^(1000)!!!!!!!!!! That's a number that a current computer can't process even if it literally ran till the end of the universe.

- Harsh February 29, 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