CC189 - Cracking the Coding Interview

Chapter 1 - Arrays and Strings


In [1]:
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from __future__ import unicode_literals

1.1 Is Unique

HashTable bitVector nLogn


In [2]:
def isUnique(string):
    return len(set(string)) == len(string)

In [6]:
def isUnique(string):
    charMap = {}
    for char in string:
        if char in charMap:
            return False
        charMap[char] = True
    return True

In [4]:
def isUnique(string):
    charList = []
    for char in string:
        if char in charList:
            return False
        charList.append(char)
    return True

In [7]:
for string in ['abc', 'aacc']:
    print("'{}' => {}".format(string, isUnique(string)))


'abc' => True
'aacc' => False

1.2 Check Permutaion

n hashTable order of string


In [5]:
## use sorted
def arePermutations(stringA, stringB):
    return sorted(stringA) == sorted(stringB)

In [8]:
## use character map
def charMap(string):
    return dict([(char, True) for char in string])
def arePermutations(stringA, stringB):
    return charMap(stringA) == charMap(stringB)

In [9]:
for (stringA, stringB) in [
    ('abc', 'cba'),
    ('abc', 'abc   '),
    ('abc', 'Abc'),
    ('acc', 'xyz')
]:
    print("('{}', '{}') => {}".format(stringA, stringB, arePermutations(stringA, stringB)))


('abc', 'cba') => True
('abc', 'abc   ') => False
('abc', 'Abc') => False
('acc', 'xyz') => False

1.3 URLify


In [10]:
def URL(string, length):
    return string[:length].replace(' ', '%20')

In [11]:
for (string, length) in [('Mr John Smith   ', 13), ('Somebody here  ', 13)]:
    print("('{}', {}) => '{}'".format(string, length, URL(string, length)))


('Mr John Smith   ', 13) => 'Mr%20John%20Smith'
('Somebody here  ', 13) => 'Somebody%20here'

1.4 Palindrome Permutations


In [12]:
from collections import defaultdict

def freqMap(string):
    freq = defaultdict(int)
    for char in string:
        if char.strip() != '':
            freq[char.lower()] += 1
    return freq

def isPalindromPermutation(string):
    freq = freqMap(string)
    return len([x for x in freq.values() if x == 1]) == 1 and max(freq.values()) <= 2

In [13]:
for string in [
    'Tact Coa',
    'abc ba',
    'xilin sun',
    'lucky li'
]:
    print("'{}' => {}".format(string, isPalindromPermutation(string)))


'Tact Coa' => True
'abc ba' => True
'xilin sun' => False
'lucky li' => False

1.5 One Away


In [14]:
## solution 1: check by edit type: replace or insert
def oneReplaceAway(s1, s2):
    return sum([s1[i] != s2[i] for i in range(len(s1))]) < 2
def oneInsertAway(s1, s2):
    foundDifference = False
    iA, iB = 0, 0
    while iA < len(s1) and iB < len(s2):
        if s1[iA] != s2[iB]:
            if foundDifference:
                return False
            foundDifference = True
            iA += 1
            continue
        iA += 1
        iB += 1
    return True

def oneAway(s1, s2):
    if abs(len(s1) - len(s2)) >= 2:
        return False
    if len(s1) == len(s2):
        return oneReplaceAway(s1, s2)
    if len(s1) > len(s2):
        return oneInsertAway(s1, s2)
    return oneInsertAway(s2, s1)

In [16]:
## don't check edit type
def oneAway(s1, s2):
    if abs(len(s1) - len(s2)) >= 2:
        return False
    if len(s1) < len(s2):
        s1, s2 = s2, s1
    foundDifference = False
    iA, iB = 0, 0 
    while iA < len(s1) and iB < len(s2):
        if s1[iA] != s2[iB]:
            if foundDifference:
                return False
            foundDifference = True
            if len(s1) != len(s2):
                iA += 1
                continue
        iA += 1
        iB += 1
    return True

In [17]:
for (s1, s2) in [
    ('abc', 'abc'),
    ('ple', 'pale'),
    ('pale', 'ple'),
    ('pale', 'bale'),
    ('pale', 'bake')
]:
    print("'{}', '{}' => {}".format(s1, s2, oneAway(s1, s2)))


'abc', 'abc' => True
'ple', 'pale' => True
'pale', 'ple' => True
'pale', 'bale' => True
'pale', 'bake' => False

1.6 String Compression


In [99]:
def compressed(string):
    charList = []
    i = 0
    while i < len(string) - 1:
        j = i + 1
        while j < len(string):
            if string[i] == string[j]:
                j += 1
            else:
                break
        charList.append("{}{}".format(string[i], j - i))
        i = j
    compressedString = "".join(charList)
    if len(compressedString) < len(string):
        return compressedString
    return string

In [19]:
## check in advance
def compressedLen(string):
    count = 1
    for i in range(len(string) - 1):
        if string[i+1] != string[i]:
            count += 1
    return count * 2

def compressed(string):
    if len(string) <= compressedLen(string):
        return string
    charList = []
    i = 0
    while i < len(string) - 1:
        j = i + 1
        while j < len(string):
            if string[i] == string[j]:
                j += 1
            else:
                break
        charList.append("{}{}".format(string[i], j - i))
        i = j
    return "".join(charList)

In [20]:
for string in [
    'aabcccccaaa',
    'abcdefg',
    '',
    'IkeoIIkkkkkeo',
    'AbOOOOook'
]:
    print("'{}' => '{}'".format(string, compressed(string)))


'aabcccccaaa' => 'a2b1c5a3'
'abcdefg' => 'abcdefg'
'' => ''
'IkeoIIkkkkkeo' => 'IkeoIIkkkkkeo'
'AbOOOOook' => 'AbOOOOook'

1.7 Rotate Matrix

Supposing clockwise


In [21]:
def rotated(matrix):
    N = len(matrix)
    nLayers = int(N / 2)
    for i in range(nLayers):
        for j in range(i, N - 1 -i):
            matrix[i][j], matrix[j][N - i - 1], matrix[N - i - 1][N - j - 1], matrix[N - j - 1][i] = matrix[N - j - 1][i], matrix[i][j], matrix[j][N - i - 1], matrix[N - i - 1][N - j - 1]
    return matrix

In [22]:
from pprint import pprint

matrix = [
    ['aa', 'kk', 'ac', 'oo'],
    ['cc', 'oc', 'lo', 'ls'],
    ['mf', 'wy', 'xr', 'wk'],
    ['ss', 'fs', 'pz', 'dg']
]

pprint(matrix)
print("=>")
pprint(rotated(matrix))


[['aa', 'kk', 'ac', 'oo'],
 ['cc', 'oc', 'lo', 'ls'],
 ['mf', 'wy', 'xr', 'wk'],
 ['ss', 'fs', 'pz', 'dg']]
=>
[['ss', 'mf', 'cc', 'aa'],
 ['fs', 'wy', 'oc', 'kk'],
 ['pz', 'xr', 'lo', 'ac'],
 ['dg', 'wk', 'ls', 'oo']]

1.8 Zero Matrix


In [26]:
# duplicate the matrix
# O(MN) space
from copy import deepcopy

def zeroMatrixIndex(matrix, x, y):
    newMatrix = deepcopy(matrix)
    N, M = len(matrix), len(matrix[0]) 
    for i in range(N):
        newMatrix[i][y] = 0
    for j in range(M):
        newMatrix[x][j] = 0
    return newMatrix

def zeroMatrix(matrix):
    newMatrix = deepcopy(matrix)
    N, M = len(matrix), len(matrix[0])
    for i in range(N):
        for j in range(M):
            if matrix[i][j] == 0:
                newMatrix = zeroMatrixIndex(matrix, i, j)
    return newMatrix

In [24]:
# solve in-place:
def zeroMatrix(matrix):
    N, M = len(matrix), len(matrix[0])

    # log if the first row and col contains zeros
    # save in two variables
    zeroInRow0 = 0 in matrix[0] 
    zeroInCol0 = 0 in [row[0] for row in matrix]

    # log other zeroes and save in the first row and col
    for i in range(1, N):
        for j in range(1, M):
            if matrix[i][j] == 0:
                matrix[i][0] = 0
                matrix[0][j] = 0

    # assign rows
    for i in range(1, N):
        if matrix[i][0] == 0:
            matrix[i] = [0 for x in range(M)]

    # assign cols
    for j in range(1, M):
        if matrix[0][j] == 0:
            for i in range(N):
                matrix[i][j] = 0

    return matrix

In [27]:
matrix = [
    [4, 1, 3],
    [1, 0, 5],
    [9, 10, 3],
    [8, 2, 3]
]

from pprint import pprint
pprint(matrix)
print("=>")
pprint(zeroMatrix(matrix))


[[4, 1, 3], [1, 0, 5], [9, 10, 3], [8, 2, 3]]
=>
[[4, 0, 3], [0, 0, 0], [9, 0, 3], [8, 0, 3]]

1.9 String Rotation


In [28]:
def isSubstring(s1, s2):
    return s1 in s2

def isRotation(s1, s2):
    return isSubstring(s1, s2 * 2)

In [29]:
for (s1, s2) in [
    ('waterbottle','erbottlewat'),
    ('abc', 'bca'),
    ('adasf', 'asasdfaq')
]:
    print("('{}', '{}') => {}".format(s1, s2, isRotation(s1, s2)))


('waterbottle', 'erbottlewat') => True
('abc', 'bca') => True
('adasf', 'asasdfaq') => False

In [ ]: