---
# System prepended metadata

title: CSPT25 Lecture 7

---

# CSPT25 Lecture 7
## Jewels and Stones
```
class Solution:
    """
    Understand
    jewels = "aA", stones = "aAAbbbb" --> 3
    jewels = "z", stones = "ZZ" --> 0
    jewels = "aA", stones = "aAA" --> 3
    Plan
    Put all characters in jewels in a set, then for each stone check if it's in that set
    Return the number of stones that are in that set
    Runtime: O(n) where n = len(jewels) == len(stones)
    Space: O(n) where n = len(jewels)
    """
    def numJewelsInStones(self, jewels: str, stones: str) -> int:
        j = set(jewels) # O(n) where n = len(jewels)
        numJewels = 0
        for stone in stones: # O(m) where m = len(stones)
            if stone in j: # n
                numJewels += 1
        return numJewels
```

## Smaller Numbers
```
class Solution:
    """
    nums = [8,1,2,2,3]
    output = [4,0,1,1,3]
    
    nums = [1,1,1,1]
    output = [0,0,0,0]
    
    nums = [4,3,2,1]
    output = [3,2,1,0]
    
    nums = [1,2,3,4]
    output = [0,1,2,3]
    
    Hint: You can solve this using sorting (.sort() or sorted())
    Sorting takes O(nlogn) time
    
    Brute-Force Approach
    O(n^2) time. For each number, check all other numbers to see how many
    are less than it. Append the result to an output list.
    
    Sorting
    Sort the input list, then build a dictionary from the sorted list.
    Where the key is the element and value is how many elements are smaller than it.
    Lastly, walk through the original list and use the dictionary created to 
    construct the output list
    Runtime: O(nlogn)
    Space: O(n)
    """
    def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
        sortedNums = sorted(nums) # nlogn
        numMap = {}
        for (i, num) in enumerate(sortedNums): # n
            if num not in numMap:
                numMap[num] = i
        res = []
        for num in nums: # n
            res.append(numMap[num])
        return res
```

## Keyboard Row
```
class Solution:
    """
    words = ["Hello","Alaska","Dad","Peace"]
    output = ["Alaska","Dad"]
    
    words = ["Hello", "Peace"]
    output = []
    
    words = ["ALASkA", "DAd", "tip", "x"]
    output = ["ALASkA", "DAd", "tip", "x"]
    
    Hint: You can do this with 3 sets
    Plan
    Have 3 sets, one for each row. Go through each word, start
    with the first letter and search which set it belongs to.
    Then check if the other letters in that word all belong in that same set.
    If so, then append it to the output list.
    words = ["ALASkA", "DAd", "tip", "x"]
    res = ["ALASkA", "DAd", "tip", "x"]
    Runtime: O(n * k) where n = len(words), k = max(len(word))
    Space: O(n) where n = len(words)
    """
    def findWords(self, words: List[str]) -> List[str]:
        rows = [set(["q","w","e","r","t","y","u","i","o","p"]), set(["a","s","d","f","g","h","j","k","l"]), set(["z","x","c","v","b","n","m"])]
        res = []
        for word in words: # n where n = len(words)
            rowFirstLetterBelongsTo = set()
            for row in rows: # 1
                if word[0].lower() in row:
                    rowFirstLetterBelongsTo = row
                    break
            allLettersAreInSameRow = True
            for i in range(1, len(word)): # k where k = len(word)
                if word[i].lower() not in rowFirstLetterBelongsTo:
                    allLettersAreInSameRow = False
                    break
            if allLettersAreInSameRow:
                res.append(word)
        return res
```