@@ -1458,7 +1458,346 @@ def test_25():
14581458 assert not regexMatched ("*a." , "blablablaay" )
14591459
14601460
1461- test_25 ()
1461+ """
1462+ question 26
1463+
1464+ Given a singly linked list and an integer k, remove the kth last element from
1465+ the list. k is guaranteed to be smaller than the length of the list.
1466+
1467+ The list is very long, so making more than one pass is prohibitively expensive.
1468+
1469+ Do this in constant space and in one pass.
1470+ --------------------
1471+
1472+ It's a single linked list, we can only travel from left to right follwing
1473+ the next pointer in each node.
1474+
1475+ Use two pointers to travel the linked list from left to right in one pass.
1476+ Initially p1 points to the head of the list, p2 points to the kth element of
1477+ the list. Then p1 and p2 go left along the list with the same pace,
1478+ one step at a time, until p2 reach the end of the list. p1 is pointing to the
1479+ kth last element of the list.
1480+ k = 3
1481+ a -> b -> c -> d -> e -> f -> g
1482+ ^ ^
1483+ ^ ^
1484+ return 'e'
1485+ """
1486+
1487+
1488+ def test_26 ():
1489+ pass
1490+
1491+
1492+ """
1493+ question 27
1494+ Given a string of round, curly, and square open and closing brackets, return
1495+ whether the brackets are balanced (well-formed).
1496+
1497+ For example, given the string "([])[]({})", you should return true.
1498+
1499+ Given the string "([)]" or "((()", you should return false.
1500+ ---------------------
1501+
1502+ Instintively, a stack can help use here but why?
1503+ To do this, iterate through the string:
1504+ For every opening, it needs to pair to a later unmatched closing. But considering
1505+ nesting scenarios, an opening can follow up another opening. So we need to reserve
1506+ unmatched openings somewhere. when a closing is comming, it needs to pair with
1507+ the most recent unmatched opening.
1508+ So a stack, as its Last-In-First-Out nature, is a good fit for this
1509+ Iterate through the string, process every bracket:
1510+ - if it's opening, push to the stack.
1511+ - if it's closing, pop from the stack (the stack should be non-empty) and pair them.
1512+ - If not pair, return early.
1513+ - Until we complete all brackets in the string. If the stack is empty, it's balanced.
1514+ Otherwise, unbalanced
1515+ """
1516+
1517+
1518+ def test_27 ():
1519+ pass
1520+
1521+
1522+ """
1523+ question 28
1524+ Write an algorithm to justify text. Given a sequence of words and an integer
1525+ line length k, return a list of strings which represents each line, fully
1526+ justified.
1527+
1528+ More specifically, you should have as many words as possible in each line. There
1529+ should be at least one space between each word. Pad extra spaces when necessary
1530+ so that each line has exactly length k. Spaces should be distributed as equally
1531+ as possible, with the extra spaces, if any, distributed starting from the left.
1532+
1533+ If you can only fit one word on a line, then you should pad the right-hand side
1534+ with spaces.
1535+
1536+ Each word is guaranteed not to be longer than k.
1537+
1538+ For example, given the list of words ["the", "quick", "brown", "fox", "jumps",
1539+ "over", "the", "lazy", "dog"] and k = 16, you should return the following:
1540+
1541+ ["the quick brown", # 1 extra space on the left
1542+ "fox jumps over", # 2 extra spaces distributed evenly
1543+ "the lazy dog"] # 4 extra spaces distributed evenly"
1544+
1545+ -------------------
1546+ iterate words, trying to fit in as much words as possible.
1547+ use two pointers, first pointer is the first word of current line and
1548+ second pointer is the word to check whether it can be fit in to current line.
1549+
1550+ ["the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
1551+ i1
1552+ i2
1553+ initially i1 = 0
1554+ cur_len = len(word[i1])
1555+ when add new word[i2], new length is cur_len + len(word[i2]) + 1
1556+ if cur_len is smaller or equal to k:
1557+ move i2 forward.
1558+ otherwise:
1559+ create a new line with words from i1 to i2-1;
1560+ distribute the extra spaces evenly between words starting from left
1561+ remaining_spaces = k - cur_len
1562+ number of spaces in words: total_num = i2 - i1
1563+ even space number: even_spaces = 1 + remaining_spaces // total_num
1564+ extra_remaining: remaining_spaces % total_num
1565+ move i1 to i2 as the first word and move i2 forward
1566+ """
1567+
1568+
1569+ def justify_text (words , k ):
1570+ # generate line with words [start, end)
1571+ # cur_len is the length with words and one space between words
1572+ def generate_one_line (start : int , end : int , cur_len : int ):
1573+ new_line = ""
1574+ space_num = end - start - 1
1575+ if space_num == 1 :
1576+ # only one word in the line
1577+ new_line += words [start ]
1578+ new_line += " " * (k - len (words [start ]))
1579+ return new_line
1580+ small_space_num = 1 + (k - cur_len ) // (space_num )
1581+ small_spaces = " " * small_space_num
1582+ large_spaces = small_spaces + " "
1583+ # print(f"'{large_spaces}'")
1584+ large_space_num = (k - cur_len ) % (space_num )
1585+ new_line += words [i1 ]
1586+ for i in range (1 , space_num + 1 ):
1587+ if i <= large_space_num :
1588+ new_line += large_spaces
1589+ else :
1590+ new_line += small_spaces
1591+ new_line += words [start + i ]
1592+ return new_line
1593+
1594+ lines = []
1595+ i1 = 0
1596+ cur_len = len (words [0 ])
1597+ for i2 in range (1 , len (words )):
1598+ if cur_len + len (words [i2 ]) + 1 > k :
1599+ # needs to generate new line with words in [i1, i2)
1600+ lines .append (generate_one_line (i1 , i2 , cur_len ))
1601+ i1 = i2
1602+ cur_len = len (words [i1 ])
1603+ else :
1604+ cur_len = cur_len + len (words [i2 ]) + 1
1605+ # process left_over words from i1 to the end
1606+ lines .append (generate_one_line (i1 , len (words ), cur_len ))
1607+ return lines
1608+
1609+
1610+ def test_28 ():
1611+ words = ["the" , "quick" , "brown" , "fox" , "jumps" , "over" , "the" , "lazy" , "dog" ]
1612+ k = 16
1613+ assert justify_text (words , k ) == [
1614+ "the quick brown" ,
1615+ "fox jumps over" ,
1616+ "the lazy dog" ,
1617+ ]
1618+
1619+
1620+ """
1621+ question 29
1622+ Run-length encoding is a fast and simple method of encoding strings. The basic
1623+ idea is to represent repeated successive characters as a single count and
1624+ character. For example, the string "AAAABBBCCDAA" would be encoded as
1625+ "4A3B2C1D2A".
1626+
1627+ Implement run-length encoding and decoding. You can assume the string to be
1628+ encoded have no digits and consists solely of alphabetic characters. You can
1629+ assume the string to be decoded is valid.
1630+
1631+ -------------------
1632+ "AAAABBBCCDAA"
1633+ ^
1634+ ^
1635+ 42A3B2C
1636+ ^
1637+
1638+ num = num * 10 + int(c)
1639+ """
1640+
1641+
1642+ def run_length_encoding (text ):
1643+ i1 = 0
1644+ encoded = ""
1645+ c1 = text [0 ]
1646+ for i2 in range (len (text )):
1647+ c2 = text [i2 ]
1648+ if c1 != c2 :
1649+ encoded += str (i2 - i1 )
1650+ encoded += c1
1651+ i1 = i2
1652+ c1 = c2
1653+ # process left_over
1654+ encoded += str (len (text ) - i1 )
1655+ encoded += text [i1 ]
1656+ return encoded
1657+
1658+
1659+ def run_length_decoding (encoded ):
1660+ num = 0
1661+ text = ""
1662+ for i2 in range (len (encoded )):
1663+ c = encoded [i2 ]
1664+ if "0" <= c <= "9" :
1665+ num = num * 10 + int (c )
1666+ else :
1667+ # decode sequence of one character
1668+ text += c * num
1669+ num = 0
1670+ return text
1671+
1672+
1673+ def test_29 ():
1674+ text = "AAAABBBCCDAA"
1675+ assert run_length_decoding (run_length_encoding (text )) == text
1676+ text = "AAAAAAAAAAAAAAAABBBCCDDDDDDDDDDDAA"
1677+ assert run_length_decoding (run_length_encoding (text )) == text
1678+
1679+
1680+ """
1681+ question 30
1682+ You are given an array of non-negative integers that represents a
1683+ two-dimensional elevation map where each element is unit-width wall and the
1684+ integer is the height. Suppose it will rain and all spots between two walls get
1685+ filled up.
1686+
1687+ Compute how many units of water remain trapped on the map in O(N) time and O(1)
1688+ space.
1689+
1690+ For example, given the input [2, 1, 2], we can hold 1 unit of water in the
1691+ middle.
1692+
1693+ Given the input [3, 0, 1, 3, 0, 5], we can hold 3 units in the first index, 2 in
1694+ the second, and 3 in the fourth index (we cannot hold 5 since it would run off
1695+ to the left), so we can trap 8 units of water.
1696+
1697+ -------------------
1698+ [2,1,2]
1699+ | |
1700+ | | |
1701+ for ith element,
1702+ - left_max_wall is the max height in heights[0, i],
1703+ - right_max_wall is the max height in heights[i, N-1]
1704+ so the water height is min(left_max_wall, right_max_wall) - cur_wall_height
1705+
1706+ [2,1,2]
1707+ left_max_array: [2,2,2]
1708+ right_max_array:[2,2,2]
1709+
1710+
1711+ left_max_array = [0] * N
1712+ left_max_array[0] = heights[0]
1713+ for i in range(1, len(heights)):
1714+ left_max_array[i] = max(left_max_array[i-1], heights[i])
1715+ right_max_array = [0] * N
1716+ right_max_array[N-1] = heights[N-1]
1717+ for i in range(N-2, -1, -1):
1718+ right_max_array = max(right_max_array(i+1), heights[i])
1719+ time O(N), space O(N)
1720+ TODO how to optimize to time O(N), space O(1)
1721+ """
1722+
1723+
1724+ def totalTrappedWater (heights ):
1725+ N = len (heights )
1726+ left_max_array = [0 ] * N
1727+ left_max_array [0 ] = heights [0 ]
1728+ for i in range (1 , N ):
1729+ left_max_array [i ] = max (left_max_array [i - 1 ], heights [i ])
1730+ right_max_array = [0 ] * N
1731+ right_max_array [N - 1 ] = heights [N - 1 ]
1732+ for i in range (N - 2 , - 1 , - 1 ):
1733+ right_max_array [i ] = max (right_max_array [i + 1 ], heights [i ])
1734+ water = 0
1735+ for i in range (N ):
1736+ water += min (left_max_array [i ], right_max_array [i ]) - heights [i ]
1737+ return water
1738+
1739+
1740+ def test_30 ():
1741+ assert totalTrappedWater ([2 , 1 , 2 ]) == 1
1742+ assert totalTrappedWater ([3 , 0 , 1 , 3 , 0 , 5 ]) == 8
1743+
1744+
1745+ """
1746+ question 31
1747+ The edit distance between two strings refers to the minimum number of character
1748+ insertions, deletions, and substitutions required to change one string to the
1749+ other. For example, the edit distance between “kitten” and “sitting” is three:
1750+ substitute the “k” for “s”, substitute the “e” for “i”, and append a “g”.
1751+
1752+ Given two strings, compute the edit distance between them.
1753+
1754+ -------------------
1755+ kitten
1756+ ^
1757+ sitting
1758+ ^
1759+
1760+ if c1==c2:
1761+ i1++ i2++
1762+ else:
1763+ a. delete: i1++ -> go right
1764+ b. insert: i2++ -> go down
1765+ c. replace: i1++ i2++ -> go right-down
1766+ steps ++
1767+
1768+ DP bottom-up
1769+ k i t t e n
1770+ s 1 2 3 4 5 6
1771+ i 2 1 2 3 4 5
1772+ t 3 2 1 2 3 4
1773+ t 4 3 2 1 2 3
1774+ i 5 4 3 2 2 3
1775+ n 6 5 4 3 3 2
1776+ g 7 6 5 4 4 3
1777+ """
1778+
1779+
1780+ def editDistance (src , dest ):
1781+ init = 0 if src [0 ] == dest [0 ] else 1
1782+ pre = list (range (init , init + len (src )))
1783+ cur = [0 ] * len (src )
1784+ for i in range (1 , len (dest )):
1785+ cur [0 ] = pre [0 ] + 1
1786+ for j in range (1 , len (src )):
1787+ if src [j ] == dest [i ]:
1788+ cur [j ] = pre [j - 1 ]
1789+ else :
1790+ cur [j ] = min (min (pre [j - 1 ], pre [j ]), cur [j - 1 ]) + 1
1791+ pre = cur
1792+ cur = [0 ] * len (src )
1793+ return pre [len (src ) - 1 ]
1794+
1795+
1796+ def test_31 ():
1797+ assert editDistance ("kitten" , "sitting" ) == 3
1798+ assert editDistance ("sigtten" , "sitting" ) == 3
1799+
1800+
14621801"""
14631802question 32 TODO
14641803This problem was asked by Jane Street.
0 commit comments