LeetCode `Top Interview Questions` `Medium` Part I

271 阅读13分钟

127. Word Ladder

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
Only one letter can be changed at a time.
Each transformed word must exist in the word list.
Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
  • You may assume no duplicates in the word list.
  • You may assume beginWord and endWord are non-empty and are not the same.

Example 1:

Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

Output: 5

Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

Example 2:

Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

Output: 0

Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.

Solution:

func ladderLength(beginWord string, endWord string, wordList []string) int {
	if len(beginWord) != len(endWord) {
		return 0
	}

	wordMap := make(map[string]bool)
	for _, s := range wordList {
		wordMap[s] = true
	}

	vis := make(map[string]bool)
	vis[beginWord] = true
	dist := 1
	for !contains(endWord, vis) && len(vis) > 0 {
		nextVis := make(map[string]bool)
		for s := range vis {
			for i := 0; i < len(s); i++ {
				for c := 'a'; c <= 'z'; c++ {
					next := s[:i] + string(c) + s[i+1:]
					if !contains(next, wordMap) {
						continue
					}

					nextVis[next] = true
					delete(wordMap, next)
				}
			}
		}
		vis = nextVis
		dist++
	}

	if contains(endWord, vis) {
		return dist
	}

	return 0
}

func contains(s string, m map[string]bool) bool {
	if _, ok := m[s]; ok {
		return true
	}

	return false
}

148. Sort List

Sort a linked list in O(n log n) time using constant space complexity.

Example 1:

Input: 4->2->1->3
Output: 1->2->3->4

Example 2:

Input: -1->5->3->4->0
Output: -1->0->3->4->5

Solution

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */

//mergesort in link list
func sortList(head *ListNode) *ListNode {
    if head == nil {
        return head
    }
    
    if head.Next == nil {
        return head
    }
 
    slow := head
    fast := head.Next
    //find the middle
    for fast != nil  && fast.Next != nil {
        slow = slow.Next
        fast = fast.Next.Next
    }
    
    nextHalfHead := slow.Next
    slow.Next = nil
    l1 := sortList(head)
    l2 := sortList(nextHalfHead)
    
    dummy := new(ListNode)
    cur := dummy
    for l1 != nil && l2 != nil {
        if l1.Val < l2.Val {
            cur.Next=l1
            l1 = l1.Next
            cur = cur.Next
        } else {
            cur.Next=l2
            l2 = l2.Next
            cur = cur.Next
        }
    }
    if l1 == nil {
        cur.Next = l2
    } else {
        cur.Next = l1
    }
    
    return dummy.Next
}

279. Perfect Squares

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.

Example 1:

Input: n = 12
Output: 3 
Explanation: 12 = 4 + 4 + 4.

Example 2:

Input: n = 13
Output: 2
Explanation: 13 = 4 + 9.

Solution

func numSquares(n int) int {
	cache := make(map[int]int)
	cache[0] = 0
	return doNumSquares(n, cache)
}

func doNumSquares(n int, cache map[int]int) int {
	if found, ok := cache[n]; ok {
		return found
	}

	res := math.MaxInt32
	for i := 1; i*i <= n; i++ {
		target := n - i*i
		res = min(res, doNumSquares(target, cache)+1)
	}
	cache[n] = res
	return res
}

func min(a, b int) int {
	if a > b {
		return b
	}
	return a
}

131. Palindrome Partitioning

Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.

Example:

Input: "aab"
Output:
[
  ["aa","b"],
  ["a","a","b"]
]

Solution

func partition(s string) [][]string {
    
    if len(s) == 0 {
        return [][]string{}
    }
    
    
    length := len(s)
    
    result := [][]string{}
    
    for pivotN := 1;pivotN <= length;pivotN++ {
        if !isPalindrome(s[:pivotN]) {
            continue
        }
        
        if pivotN == len(s) {
            result = append(result, []string{s})
            continue
        }
        // recursive
        tmp := partition(s[pivotN:])
        for _, t := range tmp {
            n := append([]string{s[:pivotN]}, t...)
            result = append(result, n)
        }
        
        
    }
    
    return result
}

200. Number of Islands

Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

Example 1:

Input: grid = [
  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
Output: 1

Example 2:

Input: grid = [
  ["1","1","0","0","0"],
  ["1","1","0","0","0"],
  ["0","0","1","0","0"],
  ["0","0","0","1","1"]
]
Output: 3

Solution

func numIslands(grid [][]byte) int {
    if(grid == nil || len(grid) == 0 || len(grid[0]) == 0) {
         return 0
    }
    height := len(grid)
    width := len(grid[0])
    result := 0
    
    for i := 0; i< height; i++ {
        for j := 0; j < width; j++ {
            result += rushIsland(grid, i, j)
        }
    }
    
    return result
}

func rushIsland(grid [][]byte, i int, j int) int {
    if (i < 0 || i >= len(grid) || j < 0 || j >= len(grid[0]) || grid[i][j] != '1') {
        return 0
    }
    grid[i][j] = '0'
    rushIsland(grid, i+1, j)
    rushIsland(grid, i-1, j)
    rushIsland(grid, i, j+1)
    rushIsland(grid, i, j-1)
    return 1
}

Failed TestCases:
[["0","1","0"],["1","0","1"],["0","1","0"]]
[["1","1","1"],["0","1","0"],["1","1","1"]]
[["1","0","1","1","1"],["1","0","1","0","1"],["1","1","1","0","1"]]
[["1"],["1"]]

152. Maximum Product Subarray

Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.

Example 1:

Input: [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.

Example 2:

Input: [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.

Solution

func maxProduct(nums []int) int {
    r := nums[0]
    length := len(nums)
    imax := r
    imin := r
    for i:= 1; i < length; i++ {
        if nums[i] < 0 {
            imax, imin = imin, imax
        }
        imax = max(nums[i], nums[i] * imax)
        imin = min(nums[i], nums[i] * imin)
        r = max(r, imax)
    }
    return r
}

func max(x int, y int) int {
    if x > y {
        return x
    }
    return y
}

func min(x int, y int) int {
    if x < y {
        return x
    }    
    return y
}

236. Lowest Common Ancestor of a Binary Tree

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]


Example 1:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes 5 and 1 is 3.

Example 2:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

Solution

/**
 * Definition for TreeNode.
 * type TreeNode struct {
 *     Val int
 *     Left *ListNode
 *     Right *ListNode
 * }
 */
 func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
     if root == nil || root == p || root == q {
         return root
     }
     left := lowestCommonAncestor(root.Left, p, q)
     right := lowestCommonAncestor(root.Right, p, q)
     if left != nil && right != nil {
         return root
     }
     if left != nil { return left }
     return right
}

395. Longest Substring with At Least K Repeating Characters

Find the length of the longest substring T of a given string (consists of lowercase letters only) such that every character in T appears no less than k times.

Example 1:

Input:
s = "aaabb", k = 3

Output:
3

The longest substring is "aaa", as 'a' is repeated 3 times.

Example 2:

Input:
s = "ababbc", k = 2

Output:
5

The longest substring is "ababb", as 'a' is repeated 2 times and 'b' is repeated 3 times.

Solution

func longestSubstring(s string, k int) int {
    return longestSubstringHelper(s, 0, len(s), k)
}

func longestSubstringHelper(s string, start int, end int, k int) int {
    if start >= end{
        return 0
    }
    appearance := [26]int{}
    for i := start; i < end; i++  {
        appearance[int(s[i]-'a')]++
    }
    
    for i := start; i < end; i++ {
        index := i
        if (appearance[int(s[index]-'a')] > 0 && appearance[int(s[index]-'a')] < k) {
            right := longestSubstringHelper(s, index+1, end, k)
            left := longestSubstringHelper(s, start, index,k)
            return max(right, left)
        }
    }
    return end - start 
}

func max(x int, y int) int {
    if x > y {
        return x
    }
    return y
}

179. Largest Number

Given a list of non negative integers, arrange them such that they form the largest number.

Example 1:

Input: [10,2]
Output: "210"

Example 2:

Input: [3,30,34,5,9]
Output: "9534330"
Note: The result may be very large, so you need to return a string instead of an integer.

Solution

import (
    "strconv"
    "sort"
    "strings"
)

type ByLength []string

// 重写函数,修改排序的实现,完成排序
// 目前来看是需要修改ByLength, Swap, Less三个函数
func (b ByLength) Len() int {
    return len(b)
}

func (b ByLength) Swap(i, j int) {
    b[i], b[j] = b[j], b[i]
}

func (b ByLength) Less(i, j int) bool {
    return (b[i] + b[j]) > (b[j] + b[i])
}

func largestNumber(nums []int) string {
    num := make([]string, 0)
    for i := 0; i < len(nums); i++ {
        num = append(num, strconv.Itoa(nums[i]))   
    }
    sort.Sort(ByLength(num))
    
    numStr := strings.Join(num, "")
    numStr = strings.TrimLeft(numStr, "0")
    if numStr == "" {
        numStr = "0"
    }
    return numStr
}

208. Implement Trie (Prefix Tree)

Implement a trie with insert, search, and startsWith methods.

Example:

Trie trie = new Trie();

trie.insert("apple");
trie.search("apple");   // returns true
trie.search("app");     // returns false
trie.startsWith("app"); // returns true
trie.insert("app");   
trie.search("app");     // returns true
Note:

You may assume that all inputs are consist of lowercase letters a-z.
All inputs are guaranteed to be non-empty strings.

Solution

type Trie struct {
    next [26]*Trie
    isWord bool
}


/** Initialize your data structure here. */
func Constructor() Trie {
    return Trie{}
}


/** Inserts a word into the trie. */
func (this *Trie) Insert(word string)  {
    cur := this
    for _, s := range word {
        if cur.next[int(s - 'a')] == nil {
            cur.next[int(s - 'a')] = new(Trie)
        }
        cur = cur.next[int(s - 'a')]
    }
    cur.isWord = true
}


/** Returns if the word is in the trie. */
func (this *Trie) Search(word string) bool {
    cur := this
    for _, s := range word {
        if cur.next[int(s - 'a')] == nil {
            return false
        }
        cur = cur.next[int(s - 'a')]
    }
    if cur.isWord == false {
        return false
    }
    return true
}


/** Returns if there is any word in the trie that starts with the given prefix. */
func (this *Trie) StartsWith(prefix string) bool {
    cur := this
    for _, s := range prefix {
        if cur.next[int(s - 'a')] == nil {
            return false
        }
        cur = cur.next[int(s - 'a')]
    }
    return true
}


/**
 * Your Trie object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Insert(word);
 * param_2 := obj.Search(word);
 * param_3 := obj.StartsWith(prefix);
 */

134. Gas Station

There are N gas stations along a circular route, where the amount of gas at station i is gas[i].
You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.
Return the starting gas station's index if you can travel around the circuit once in the clockwise direction, otherwise return -1.
Note:

  • If there exists a solution, it is guaranteed to be unique.
  • Both input arrays are non-empty and have the same length.
  • Each element in the input arrays is a non-negative integer.

Example 1:

Input: 
gas  = [1,2,3,4,5]
cost = [3,4,5,1,2]

Output: 3

Explanation:
Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 4. Your tank = 4 - 1 + 5 = 8
Travel to station 0. Your tank = 8 - 2 + 1 = 7
Travel to station 1. Your tank = 7 - 3 + 2 = 6
Travel to station 2. Your tank = 6 - 4 + 3 = 5
Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3.
Therefore, return 3 as the starting index.

Example 2:

Input: 
gas  = [2,3,4]
cost = [3,4,3]

Output: -1

Explanation:
You can't start at station 0 or 1, as there is not enough gas to travel to the next station.
Let's start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 0. Your tank = 4 - 3 + 2 = 3
Travel to station 1. Your tank = 3 - 3 + 3 = 3
You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3.
Therefore, you can't travel around the circuit once no matter where you start.

Solution

func canCompleteCircuit(gas []int, cost []int) int {
    sum1 := 0
    for _, i := range gas {
        sum1 += i
    }
    cost1 := 0
    for _, i := range cost {
        cost1 += i
    }
    if sum1 < cost1 {
        return -1
    }
    
    tank := 0
    start := 0
    next := 0
    // 只要加油站提供的汽油大于消耗,一定能跑完
    for {
        diff := gas[next] - cost[next]
        tank += diff
        next = (next + 1) % len(gas)
        // 检测是否正好能跑完一圈
        if tank >= 0 {
            if start == next {
                return start
            }
            continue
        }
        // 当前起始点不行,换下一个
        start = next
        tank = 0
    }
    return -1
}

210. Course Schedule II 

There are a total of n courses you have to take, labeled from 0to n-1.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses.
There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.

Example 1:

Input: 2, [[1,0]] 
Output: [0,1]
Explanation: There are a total of 2 courses to take. To take course 1 you should have finished   
             course 0. So the correct course order is [0,1] .

Example 2:

Input: 4, [[1,0],[2,0],[3,1],[3,2]]
Output: [0,1,2,3] or [0,2,1,3]
Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both     
             courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0. 
             So one correct course order is [0,1,2,3]. Another correct ordering is [0,2,1,3] .

Note:

  • The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
  • You may assume that there are no duplicate edges in the input prerequisites.

Solution

func findOrder(numCourses int, prerequisites [][]int) []int {
    courses := make([]bool, numCourses) // course 是否出现    
    neighbors := make([][]int, numCourses) // 节点的下一个毗邻节点
    indegree := make([]int, numCourses) // 入度
    
    for _, prereq := range prerequisites {
        from, to := prereq[1], prereq[0]
        courses[from], courses[to] = true, true
        neighbors[from] = append(neighbors[from], to)
        indegree[to]++
    }
    
    res := []int{}
    queue := []int{}
    for i := 0; i < numCourses; i++ {
        // bfs 查找,寻找入度为0的点(根节点)来作为入口
        if courses[i] && indegree[i] == 0 {
            queue = append(queue, i)
        }
        // 考虑孤立节点
        if !courses[i] {
            res = append(res, i)
        }
    }
    
    for len(queue) > 0{
        newQueue := []int{}
        for i := 0; i < len(queue); i++ {
            from := queue[i]
            res = append(res, from)
            // 遍历当前课程指向的所有课程
            for _, n := range neighbors[from] {
                indegree[n]--
                // 入度为0,表示指向度下一阶段课程的前导课程已经全部修完
                if indegree[n] == 0 {
                    newQueue = append(newQueue, n)
                }
            }
        }
        queue = newQueue
    }
    
    if len(res) == numCourses {
        return res
    }
    
    return []int{}
}

138. Copy List with Random Pointer

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
The Linked List is represented in the input/output as a list of n nodes. Each node is represented as a pair of [val, random_index] where:
val: an integer representing Node.val
random_index: the index of the node (range from 0 to n-1) where random pointer points to, or null if it does not point to any node.

Example 1:

Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
Output: [[7,null],[13,0],[11,4],[10,2],[1,0]]

Example 2:

Input: head = [[1,1],[2,1]]
Output: [[1,1],[2,1]]

Example 3:

Input: head = [[3,null],[3,0],[3,null]]
Output: [[3,null],[3,0],[3,null]]

Example 4:

Input: head = []
Output: []
Explanation: Given linked list is empty (null pointer), so return null.

Constraints:

  • -10000 <= Node.val <= 10000
  • Node.random is null or pointing to a node in the linked list.
  • Number of Nodes will not exceed 1000.

Solution

/**
 * Definition for a Node.
 * type Node struct {
 *     Val int
 *     Next *Node
 *     Random *Node
 * }
 */

func copyRandomList(head *Node) *Node {
    if head == nil {
        return head
    }
    headMap := map[*Node]*Node{}
    p := head
    
    for p != nil {
        headMap[p] = new(Node)
        p = p.Next
    }
    
    for k, v := range headMap {
        v.Val = k.Val
        
		if k.Next != nil {
			v.Next = headMap[k.Next]
		}
		if k.Random != nil {
			v.Random = headMap[k.Random]
		}
    }
    return headMap[head]
}

105. Construct Binary Tree from Preorder and Inorder Traversal

Given preorder and inorder traversal of a tree, construct the binary tree.

Note: You may assume that duplicates do not exist in the tree.

For example, given

preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]

Return the following binary tree:

    3
   / \
  9  20
    /  \
   15   7

Solution

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func buildTree(preorder []int, inorder []int) *TreeNode {
    // 前序遍历第一个永远是root节点
    // 中序遍历左边都是左子树,右边都是右子数
    shownMap := make(map[int]int)
    for i, v := range inorder {
        shownMap[v] = i
    }
    return build (preorder, inorder, 0, 0, len(inorder) - 1, shownMap)
    
}

func build (pre []int, inorder []int, p int, inStart int, inEnd int, shownMap map[int]int) *TreeNode {
    if inStart > inEnd || inStart < 0 || inEnd >= len(inorder) || p >= len(pre) {
        return nil
    }
    
    root := new(TreeNode)
    root.Val = pre[p]
    index := shownMap[root.Val]
    root.Left = build(pre, inorder, p+1, inStart, index-1, shownMap)
    root.Right = build(pre, inorder, p + index - inStart + 1, index+1, inEnd, shownMap)
    return root
    
}

207. Course Schedule

There are a total of numCourses courses you have to take, labeled from 0 to numCourses-1.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

Example 1:

Input: numCourses = 2, prerequisites = [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take. 
             To take course 1 you should have finished course 0. So it is possible.

Example 2:

Input: numCourses = 2, prerequisites = [[1,0],[0,1]]
Output: false
Explanation: There are a total of 2 courses to take. 
             To take course 1 you should have finished course 0, and to take course 0 you should
             also have finished course 1. So it is impossible.

Constraints:

  • The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
  • You may assume that there are no duplicate edges in the input prerequisites.
  • 1 <= numCourses <= 10^5

Solution

func canFinish(numCourses int, prerequisites [][]int) bool {
    courses := make([]bool, numCourses)
    indegree := make([]int, numCourses)
    neighbors := make([][]int, numCourses)
    
    for _, pre := range prerequisites {
        from, to := pre[1], pre[0]
        courses[from], courses[to] = true, true
        indegree[to]++
        neighbors[from] = append(neighbors[from], to)
    }
    
    res := 0
    queue := []int{}
    for c :=  range courses {
        if courses[c] && indegree[c] == 0 {
            queue = append(queue, c)
        }
        if !courses[c] {
            res += 1
        }
    }
    
    // bfs
    for len(queue) > 0 {
        newQueue := []int{}
        for i := 0; i < len(queue); i++ {
            course := queue[i]
            res += 1
            for _, n := range neighbors[course] {
                indegree[n]--
                // 如果入度为0,那么这个课程的所有前导课程都已经修完,可以查看下面度课程学什么了
                if indegree[n] == 0 {
                    newQueue = append(newQueue, n)
                }
            }
        }
        queue = newQueue
    }
    
    if res == numCourses {
        return true
    }
    return false
}

322. Coin Change

You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.

Example 1:

Input: coins = [1, 2, 5], amount = 11
Output: 3 
Explanation: 11 = 5 + 5 + 1

Example 2:

Input: coins = [2], amount = 3
Output: -1

Note: You may assume that you have an infinite number of each kind of coin.

Solution

func coinChange(coins []int, amount int) int {
    m := amount + 1
    dp := []int{}
    for i := 0; i < amount + 1; i++ {
        dp = append(dp, m)
    }
    dp[0] = 0
    
    for i := 1; i <= amount; i++ {
        for j := 0; j < len(coins); j ++ {
            if coins[j] <= i {
                dp[i] = min(dp[i], dp[i - coins[j]] + 1)
            }
        }
    }
    if dp[amount] > amount {
        return -1    
    }
    return dp[amount]
}

func min (x int, y int) int {
    if x < y {
        return x
    }
    return y
}

227. Basic Calculator II

Implement a basic calculator to evaluate a simple expression string.
The expression string contains only non-negative integers, +, -, *, / operators and empty spaces . The integer division should truncate toward zero.

Example 1:

Input: "3+2*2"
Output: 7

Example 2:

Input: " 3/2 "
Output: 1

Example 3:

Input: " 3+5 / 2 "
Output: 5

Note:

  • You may assume that the given expression is always valid.
  • Do not use the eval built-in library function.

Solution

func calculate(s string) int {
    s = removeWhiteSpaces(s)
    if len(s) == 0 {
        return 0
    }
    return calculateHelper(s, 0, '+')
}

func calculateHelper(s string, res int, lastOp byte) int {
	if len(s) == 0 {
		return res
	}

	i := 0
	for i < len(s) && (s[i] != '+' && s[i] != '-') {
		i++
	}

	num := calculateOnlyMulOrDiv(s[:i])
	switch lastOp {
	case '+':
		res += num
	default:
		res -= num
	}
	if len(s) == i {
		return calculateHelper("", res, ' ')
	}

	return calculateHelper(s[i+1:], res, s[i])

}

func calculateOnlyMulOrDiv(s string) int {
	return calculateOnlyMulOrDivHelper(s, 1, '*')
}

func calculateOnlyMulOrDivHelper(s string, res int, lastOp byte) int {
	if len(s) == 0 {
		return res
	}

	i := 0
	for i < len(s) && (s[i] != '*' && s[i] != '/') {
		i++
	}

	num, _ := strconv.Atoi(s[:i])
	switch lastOp {
	case '*':
		res *= num
	default:
		res /= num
	}
	if len(s) == i {
		return calculateOnlyMulOrDivHelper("", res, ' ')
	}

	return calculateOnlyMulOrDivHelper(s[i+1:], res, s[i])
}


func removeWhiteSpaces(s string) string {
    res := []byte{}
    for i := 0; i < len(s); i++ {
        if s[i] == ' ' {
            continue
        }
        res = append(res, s[i])
    }
    return string(res)
}