Thursday, July 8, 2010

Checking whether a binary tree is balanced or not using recursion

Balanced: no path from root to leaf node is longer than another such path by 1.

The code is just so elegant...



this can be extended to general trees with more than two children by examining all children's maxDepth or minDepth.

ArrayList vs. LinkedList

There has been quite a bit discussion already. So just sum up by a few words:

ArrayList
  • Lookup by index is O(1). (in Java, it implements RandomAccess) Suitable for dataset with random access pattern.
  • Insertion can be expensive. Worst case O(n).
    1. Insertion to the middle can cause shifting.
    2. Insertion to the end can cause changing in the size of the internal storage, usually doubling.
  • Deletion Depending on the implementation, it may vary a bit. Generally not bad.
LinkedList
  • Lookup by index is O(n) in worst case. (in Java, it implements Queue). Suitable for data set that most of operations against it is iteration, or access mostly happens at the beginning or the end, such as FIFO queues, FILO stacks.
  • Insertion is O(1)
  • Deletion
    1. Deletion by reference is O(1)
    2. Deletion by value is as bad as lookup.
General thoughts:

Comparing two data structures, always at least think from two perspectives:
  1. operations: lookup, insertion, deletion, manipulation.
  2. input data characteristics: matching the characteristics with the cost of each operation to find the better data structure to solve your problem.

Hashtable

Disadvantage: generally, it wastes spaces.
Advantage: generally, it does fast lookup.

Three normal types: Chained, Chained Scattered, Open Scatter



Tuesday, July 6, 2010

Finding all numbers which are smaller than K and only divisible by 2, 3, and 5

This may not be the most optimal solution...

Essentially we are looking for all possible {(x, y, z) | (2^x * 3^y * 5^z) <= K}
  1. When x+y+z = 1, we get {2, 3, 5},

  2. Let:

    S(i) = { (2^x * 3^y * 5^z) | (2^x * 3^y * 5^z) < K and (x + y + z = i)}

    S(i, j) = Union of all s in S(i-1, t) * j that:
    a. t and j belong to {2, 3, 5}
    b. t >= j
    c. s <= K

    for example:
    S(2,2) = {2, 3, 5} * 2 = {4, 6, 10}
    S(2,3) = {3, 5} * 3 = {9, 15}
    S(2,5) = {5} * 5 = {15}

  3. S(i) = S(i-1, 2) + S(i -1, 3) + S(i-1, 5).

    for example:
    S(2) = S(2,2) + S(2,3) + S(2, 5)

  4. Stops when S(i) is empty.