3/27/2017

JNI Should I call DeleteLocalRef

In JNI, FindClass method returns a local reference.
Sample code:
 jclass arrayListClass = env->FindClass("java/util/ArrayList");
 ....
 env->DeleteLocalRef(arrayListClass);
Is it necessary to call DeleteLocalRef ? In fact, it is unnecessary to call DeleteLocalRef in most of the cases. However, JNI has a limited (but configurable) number of local references available. So, the best practice is to delete if the reference is created in a loop

3/21/2017

C++ Version header template

Make a note for the usage of my version.hpp.
I can not only get the string of version from LIB_VERSION but also get major/minor/patch versions separately.
#pragma once
//  A *string*, LIB_VERSION, in the form "x.y.[z]"
//  where x is the major version number,
//  y is the minor version number,
//  and z is the patch level

#define LIB_VERSION_MAJOR    0
#define LIB_VERSION_MINOR    4
#define LIB_VERSION_PATCH    12

#define AUX_STR_EXP(__A)     #__A
#define AUX_STR(__A)         AUX_STR_EXP(__A)

#define LIB_VERSION          AUX_STR(LIB_VERSION_MAJOR) "."
        \ AUX_STR(LIB_VERSION_MINOR) "." 
        \ AUX_STR(LIB_VERSION_PATCH)
  

Besides, I wrote a python script to update the patch.
REG_VERSION_LINE = r"ASUS_VISION_LIB_VERSION_PATCH.  +([0-9:]+)"

def changeSoVersion(versionFile):
    # Read in the file
    filedata = None
    with open(versionFile, 'r') as file:
        filedata = file.read()
        matches = re.finditer(REG_VERSION_LINE, filedata)
        for matchNum, match in enumerate(matches):
            oldVersion = match.group(1)
            newVersion = str(int(match.group(1)) + 1)
            print oldVersion
            print newVersion
            if len(oldVersion) > 0 and len(newVersion) > 0:
                filedata = filedata.replace(oldVersion, newVersion)

    # Write the file out again
    with open(versionFile, 'w') as file:
        file.write(filedata)
  

3/03/2017

什麼是 closed-form solution and numerical solution

最近正在學解決multivariate analysis和optimalization問題, 遇到一個英文名詞close-form solution. close-form solution中文文獻稱閉合解. 白來來說就是給予一些觀察到的資料, 然後問題可以用函數和數學運算來表示, 這樣的方程式就是close-form solution or numerical solution, 差別在於一個是exact, 一個是approximate. 舉例來說, 在Linear regression中的 Least square equation就是close-form solution, Non-linear regression是numerical solution.

2/05/2017

[Interview type questions] Task sequence arragnement

Given a task sequence and the cool down time(k), rearrange the task sequence such that the execution time is minimal.
Solution:
 public static void main(String[] args) {
  char[] task = findBestTaskArrangement(String.valueOf("AAABBB").toCharArray(), 2);
  System.out.println(task);
  System.out.println("Total time: " + computeTatalTaskTime(task, 2));
  // ABABAB
  // Total time:8
 }
 
 public static char[] findBestTaskArrangement(char[] tasks, int k) {
  int n = tasks.length;
  Map<Character, Integer> map = new HashMap<>();
  for (char task : tasks) {
   map.put(task, map.getOrDefault(task, 0) + 1);
  }

  PriorityQueue<Task> queue = new PriorityQueue<>(new Comparator<Task>() {

   @Override
   public int compare(Task a, Task b) {
    return b.frequency - a.frequency;
   }
  });

  for (Map.Entry<Character, Integer> entry : map.entrySet()) {
   queue.offer(new Task(entry.getKey(), entry.getValue()));
  }
  
  tasks = new char[n];
  int i = 0;
  while (!queue.isEmpty()) {
   int c = 0;
   List<Task> nextRoundTask = new ArrayList<>();
   while(c++ < k && !queue.isEmpty()) {
    Task task = queue.poll();
    task.frequency--;
    // Locate the next empty slot
    tasks[i++] = task.id;
    if (task.frequency > 0)
     nextRoundTask.add(task);
   }
   for (Task task : nextRoundTask) {
    queue.offer(task);
   }
  }

  return tasks;
 }

 // helper class
 public static class Task {
  char id;
  int frequency;

  Task(char i, int f) {
   id = i;
   frequency = f;
  }
 }

 public static int computeTatalTaskTime(char[] tasks, int k) {
  HashMap<Character, Integer> taskLastTimeMap = new HashMap<>();
  int currTime = 0;
  for (char task : tasks) {
   if (taskLastTimeMap.containsKey(task)) {
    int exceptedTime = taskLastTimeMap.get(task) + k + 1;
    if (exceptedTime > currTime) {
     currTime = exceptedTime;
    } else
     currTime++;
   } else {
    currTime++;
   }
   taskLastTimeMap.put(task, currTime);
  }
  return currTime;
 }

[Interview type questions] MinQueue

Leetcode had a question about min stack, but there is no question about min queue. In this article, I wrote a simple one for min queue.

Solution:
 public static void main(String[] args) {
  MinQueue queue = new MinQueue();
  // Input 3 -> 1 -> 4 -> 2
  queue.offer(3).offer(1).offer(4).offer(2);
  //  0 0 0 1 1 1
  while(queue.isEmpty() == false) {
   System.out.println(queue.getMin());
   queue.poll();
  }
  // Output should be 1 -> 1 -> 2 -> 2
 }
 
 static class MinQueue {
  private Queue<Integer> mQueue = new LinkedList<>();
  private Deque<Integer> mMinDeque = new ArrayDeque<>();
  
  MinQueue offer(int val) {
   int min = val;
   while(!mMinDeque.isEmpty() && mMinDeque.getLast() > val) {
    mMinDeque.pollLast();
    min = val;
   }
   int size = mQueue.size() - mMinDeque.size();
   for (int i = 0; i <= size; i++) {
    mMinDeque.addLast(min);
   }
   mQueue.offer(val);
   return this;
  }
  
  int poll() {
   mMinDeque.poll();
   return mQueue.poll();
  }
  
  boolean isEmpty() {
   return mQueue.isEmpty();
  }
  
  int getMin() {
   return mMinDeque.peek();
  }
 }       

2/04/2017

Given a million points (x, y), give an O(n) solution to find the k's points closest to (0, 0).

Use quick select/partial sorting to resolve.
Solution:
 static class Point {
  int x;
  int y;

  public Point(int x, int y) {
   this.x = x;
   this.y = y;
  }

  public double getDistFromCenter() {
   return Math.sqrt(x * x + y * y);
  }
 }

 public static void main(String[] args) {
  Point[] points = new Point[7];
  points[0] = new Point(0, 0);
  points[1] = new Point(1, 7);
  points[2] = new Point(2, 2);
  points[3] = new Point(2, 2);
  points[4] = new Point(3, 2);
  points[5] = new Point(1, 4);
  points[6] = new Point(1, 1);
  int k = 3;
  qSelect(points, k - 1);
  for (int i = 0; i < k; i++) {
   System.out.println("" + points[i].x + "," + points[i].y);
  }
  // Output will be
  //        0,0
  //        1,1
  //        2,2
 }

 // in-place qselect and zero-based
 static void qSelect(Point[] points, int k) {
  int l = 0;
  int h = points.length - 1;
  while (l <= h) {
   int partionInd = partition(l, h, points);
   if (partionInd == k) {
    return;
   } else if (partionInd < k) {
    l = partionInd + 1;
   } else {
    h = partionInd - 1;
   }
  }
 }

 static int partition(int l, int h, Point[] points) {
  // Random can be better
  // int p = l + new Random.nextInt(h - l + 1);
  int p = l + (h - l) / 2;
  int ind = l;
  swap(p, h, points);
  Point comparePoint = points[h];
  for (int i = l; i < h; i++) {
   if (points[i].getDistFromCenter() < comparePoint.getDistFromCenter()) {
    swap(i, ind, points);
    ind++;
   }
  }
  swap(ind, h, points);
  return ind;
 }

 static void swap(int i, int j, Point[] points) {
  Point temp = points[i];
  points[i] = points[j];
  points[j] = temp;
 }

1/28/2017

[Interview type questions] First pair non matching leaves

Input: Given two (binary) trees, return the first pair of non-matching leaves Tree 1: A, B, C, D, E, null, null Tree 2: A, D, B
Output: (E,B)

Example:
Tree1 :              
      A
     /   \
   B     C
  /  \
D    E    

Tree2 :
    A
  /    \
D     B

Solution:
 static class TreeNode {
  public TreeNode(char v) { val = v;}
  char val;
  TreeNode left;
  TreeNode right;
 }
 
 static class MyIterator {
  Stack<TreeNode> stack = new Stack<>();
  MyIterator(TreeNode root) {
   pullAll(root);
  }
  
  void pullAll(TreeNode node) {
   while(node != null) {
    stack.push(node);
    node = node.left;
   }
  }
  
  public TreeNode next() {
   TreeNode next = stack.pop();
   if (next.right != null) {
    pullAll(next.right);
   }
   return next;
  }
  
  public TreeNode nextLeaf() {
   while(hasNext()) {
    TreeNode next = next();
    if (next.left == null && next.right == null) {
     return next;
    }
   }
   return null;
  }
  
  boolean hasNext() {
   return stack.isEmpty() == false;
  }
 }
 
 public static void main(String[] args) {
  TreeNode root1 = new TreeNode('A');
  root1.left = new TreeNode('B');
  root1.right = new TreeNode('C');
  root1.left.left = new TreeNode('D');
  root1.left.right = new TreeNode('E');
  TreeNode root2 = new TreeNode('A');
  root2.left = new TreeNode('D');
  root2.right = new TreeNode('B');
  char[] res = findFirstNonMatch(root1, root2);
  System.out.println(res);
 }
 
 static char[] findFirstNonMatch(TreeNode root1, TreeNode root2) {
  MyIterator iter1 = new MyIterator(root1);
  MyIterator iter2 = new MyIterator(root2);
  while(true) {
   TreeNode leaf1 = iter1.nextLeaf();
   TreeNode leaf2 = iter2.nextLeaf();
   if (leaf1 == null || leaf2 == null) break;
   if (leaf1.val != leaf2.val) {
    return new char[] {leaf1.val, leaf2.val};
   }
  }
  return new char[] {};
 }
       

[Interview type questions] Construct Binary search tree from given preorder array

Input: Give a preorder array
Output: Tree root

Example: If the given traversal is {10, 5, 1, 7, 40, 50}, then the output should be root of following tree.
     10
   /   \
  5     40
 /  \      \
1    7      50

Solution:
 static class TreeNode {
  public TreeNode(int v) { val = v;}
  int val;
  TreeNode left;
  TreeNode right;
 }

 public static void main(String[] args) {
  //       10
  //    5     40
  //  1  7       50
  int pre[] = new int[] { 10, 5, 1, 7, 40, 50 };
  int size = pre.length;
  TreeNode root = constructTree(pre, 0, size - 1);
  printInorder(root);
 }

 public static TreeNode constructTree(int[] pre, int l, int h) {
  if (l > h) return null;
  if (l == h) return new TreeNode(pre[l]);
  TreeNode root = new TreeNode(pre[l]);
  int ind = l + 1;
  // Find the first index which is greater than or equal to root
  for (int i = l + 1; i <= h; i++) {
   if (root.val < pre[i]) {
    ind = i;
    break;
   }
  }
  root.left = constructTree(pre, l + 1, ind - 1);
  root.right = constructTree(pre, ind, h);
  return root;
 }

 public static TreeNode constructTreeIterative(int[] pre, int l, int h) {
  if (l > h) return null;
  Stack<TreeNode> stack = new Stack<>();
  TreeNode root = new TreeNode(pre[l]);
  stack.push(root);
  for (int i = l + 1 ; i <= h ; i++) {
   int val = pre[i];
   // Handle left side
   if (stack.peek().val > val) {
    TreeNode left = new TreeNode(val);
    stack.peek().left = left;
    stack.push(left);
   } else {
    // Handle right side and find its paraent
    TreeNode rightParent = null;
    while(!stack.isEmpty() && stack.peek().val < val) {
     rightParent = stack.pop();
    }
    rightParent.right = new TreeNode(val);
    stack.push(rightParent);
   }
  }
  return root;
 }

 public static void printInorder(TreeNode node) {
  if (node == null) {
   return;
  }
  printInorder(node.left);
  System.out.print(node.val + " ");
  printInorder(node.right);
 }
       

1/27/2017

[Interview type questions] Divide friends into two groups, and people in the same group do not know each other

Input: Give edges to represent their relations.
Output: Divide the friends into two groups, and people in the same group do now know each other.

Example: Give 4 persons. [0, 1] [1, 2] [1, 3]
         0 and 1 know each other, 1 and 2 know each other...
         We can take 0,2 as group 1 and 1,3 as group 2.

Solution: Use bipartite graph with BFS to resolve this problem:
  int n = 4;
  int[][] relations = new int[][] { { 0, 1 }, { 1, 2 }, { 2, 3 } };

  // Build a graph and initialize groups
  HashMap<Integer, Set<Integer>> graph = new HashMap<>();
  int[] group = new int[4];
  Arrays.fill(group, -1);
  for (int[] edge : relations) {
   Set neighbors = graph.getOrDefault(edge[0], new HashSet<>());
   neighbors.add(edge[1]);
   graph.put(edge[0], neighbors);
  }
  // BFS, start with 0
  Queue queue = new LinkedList<>();
  queue.offer(0);
  int groupdId = 0;
  group[0] = groupdId;
  while(queue.isEmpty() == false) {
   int v = queue.poll();
   groupdId = 1 - group[v];
   // Get its neighbors
   // No neighbors..
   if (graph.get(v) == null) continue;
   for (int neighbor : graph.get(v)) {
    if (group[neighbor] == -1) {
     group[neighbor] = groupdId;
     queue.offer(neighbor);
    } else if (group[neighbor] == group[v]) {
     // It cannot be divided into two group. Invalid bipartite graph
     break;
    }
   }
  }
  
  for (int g : group) {
   System.out.println(g);
  }
       

1/10/2017

Serialize/De-serialize data to a file using Flatbuffers


Read & Write

       

#include "flatbuffers/util.h"

flatbuffers::FlatBufferBuilder builder;

// Create something using builder
// ......

// Save to file
bool result = flatbuffers::SaveFile(filename.c_str(),
                                      (const char *) builder.GetBufferPointer(),
                                      (size_t) builder.GetSize(), true);

// Load from file
std::string buffer;
result = flatbuffers::LoadFile(fileName, true, &buffer);
printf("\nLoadFile Result = %d", result);


// You can write your own Save/load function
bool MySaveFile(const char *name, const char *buf, size_t len,
                     bool binary) {
  std::ofstream ofs(name, binary ? std::ofstream::binary : std::ofstream::out);
  if (!ofs.is_open()) return false;
  ofs.write(buf, len);
  return !ofs.bad();
}

bool MyLoadFileRaw(const char *name, bool binary, std::string *buf) {
  std::ifstream ifs(name, binary ? std::ifstream::binary : std::ifstream::in);
  if (!ifs.is_open()) {
    return false;
  }
  if (binary) {
    // The fastest way to read a file into a string.
    ifs.seekg(0, std::ios::end);
    auto size = ifs.tellg();
    (*buf).resize(static_cast(size));
    ifs.seekg(0, std::ios::beg);
    ifs.read(&(*buf)[0], (*buf).size());
  } else {
    // This is slower, but works correctly on all platforms for text files.
    std::ostringstream oss;
    oss << ifs.rdbuf();
    *buf = oss.str();
  }
  return !ifs.bad();
}