Wednesday 30 September 2015

Data Structure and Algorithm - Find the Longest Continuous Distinct Characters (Amazon Interview Question)

1. Problem Description
A = “aabcbcdbca”, then ans would be 4 as of “dbca”
- neer.1304 18 days ago in United States | Report Duplicate | Flag ".

2. Pseudo-code
String tempResult
String finalResult
HashSet hs
- 1. Check if this character, x, appears in hs. If yes,
    * assign tempResult to finalResult if tempResult is longer than finalResult
    * Remove entries in hs of the characters from the beginning to character x in tempResult
    * Remove the beginning to character x in tempResult
- 2. add this character into hs,
- 3. append this character into tempResult
- 4. Repeat 1,2 and 3 until reach the end of the input string
- 5. Swap tempResult and finalResult if tempResult is longer

3. C++ Implementation
// ********************************************************************************
// Implementation
// ********************************************************************************
#include <queue>
#include <string>
#include <unordered_set>

std::string FindLongestUniqueCharacterSerial(const std::string& input)
{
    if (input.empty()) {
        return std::string();
    }

    std::unordered_set<char> appearedCharacters;
    std::string uniqueCharacters;
    std::string result;
    auto iterEnd = input.end();
    for (auto iter = input.begin(); iter != iterEnd; ++iter) {
        if (appearedCharacters.find(*iter) != appearedCharacters.end()) {
            // The case of "yes", in Step 1
            if (uniqueCharacters.size() > result.size()) {
                result = uniqueCharacters;
            }

            auto iterUC = uniqueCharacters.begin();
            auto iterUCEnd = uniqueCharacters.end();
            for (; iterUC != iterUCEnd; ++iterUC) {
                if (*iterUC == *iter) {
                    break;
                }
                appearedCharacters.erase(*iterUC);
            }
            std::string(++iterUC, iterUCEnd).swap(uniqueCharacters);
        }

        // Step 2 and 3
        appearedCharacters.insert(*iter);
        uniqueCharacters.push_back(*iter);
    }

    // Step 5
    if (uniqueCharacters.size() > result.size()) {
        result.swap(uniqueCharacters);
    }

    return result;
}

// ********************************************************************************
// Test
// ********************************************************************************
#include <cassert>
void TestCasesOfFindLongestUniqueCharacterSerial()
{
    std::string testString;
    assert(FindLongestUniqueCharacterSerial(testString).empty());

    testString = "aaaaaaaaaaaaaaaaaaaa";
    assert(FindLongestUniqueCharacterSerial(testString) == "a");

    testString = "abcdefghijklmn";
    assert(FindLongestUniqueCharacterSerial(testString) == testString);

    testString = "aabcbcdbca";
    assert(FindLongestUniqueCharacterSerial(testString) == "dbca");

    testString = "bcccf";
    assert(FindLongestUniqueCharacterSerial(testString) == "bc");
}

Tuesday 29 September 2015

BTS - Print the First and Last Nodes of Each Level (Amazon Interview Question)

1. Problem Description
This is an Amazon interview question for software develop engineer from careercup. Here is the original thread,
"
Print first and last node of all the levels of a tree. 
Ex if tree is -

root->data = 1
root->left->data = 2
root->right->data = 3
root->left->right->data = 4
root->right->right->data = 6
root->right->left->data = 5
root->right->left->left->data = 7
root->right->left->left->right->data = 8

Output - 1 2 3 4 6 7 8
- neer.1304 9 days ago in United States | Report Duplicate | Flag ".

2.Analysis
Naturally it is common to think of using breadth-first search to find out all the nodes in each level and print the the first and the last node of this level.

There is one edge case that the level has only one node, and this means that the only node is the first and the last node at the same time. In this case just avoid to print it twice.

3. C++ Implementation
// ********************************************************************************
// Implementation
// ********************************************************************************
#include <cassert>
#include <memory>
#include <queue>
#include <stack>
#include <vector>

template<typename T>
struct TreeNode
{
    TreeNode(const T& d)
    : data(new T(d)), left(nullptr), right(nullptr)
    {}
    ~TreeNode()
    {
        std::shared_ptr<T>().swap(data);
    }

    std::shared_ptr<T> data;
    TreeNode* left;
    TreeNode* right;
};

template<typename T>
struct TreeConstructionBFS
{
    TreeConstructionBFS()
    {}

    TreeConstructionBFS(TreeNode<T>* p, bool left, int s, int e)
        : parent(p), isLeftChild(left), start(s), end(e)
    {}

    TreeNode<T>*    parent = nullptr;
    bool            isLeftChild = false;
    int             start = 0;
    int             end = -1;
};

template<typename T>
TreeNode<T>* ConstructTreeOnSortedValueBFS(const std::vector<T>& input)
{
    if (input.empty()) {
        return nullptr;
    }

    const int len = input.size();
    int index = len >> 1;
    TreeNode<T>* root = new TreeNode<T>(input[index]);
    std::queue<TreeConstructionBFS<T>> nodesToBuild;
    nodesToBuild.push(TreeConstructionBFS<T>(root, true, 0, index - 1));
    nodesToBuild.push(TreeConstructionBFS<T>(root, false, index + 1, len - 1));

    while (!nodesToBuild.empty()) {
        const TreeConstructionBFS<T>& curCon = nodesToBuild.front();
        if (curCon.start > curCon.end) {
            if (curCon.isLeftChild) {
                curCon.parent->left = nullptr;
            }
            else {
                curCon.parent->right = nullptr;
            }
        }
        else {
            index = (curCon.start + curCon.end) >> 1;
            TreeNode<T>* tempNode = new TreeNode<T>(input[index]);
            if (curCon.isLeftChild) {
                curCon.parent->left = tempNode;
            }
            else {
                curCon.parent->right = tempNode;
            }

            nodesToBuild.push(TreeConstructionBFS<T>(tempNode, 
                                                     true,
                                                     curCon.start,
                                                     index - 1));
            nodesToBuild.push(TreeConstructionBFS<T>(tempNode,
                                                     false,
                                                     index + 1,
                                                     curCon.end));
        }
        nodesToBuild.pop();
    }

    return root;
}

template<typename T>
void GetFirstAndLastOfEachLevelOfTree(TreeNode<T>* root,
    std::vector<TreeNode<T>*>& listOfFL)
{
    if (root == nullptr) {
        return;
    }

    std::queue<TreeNode<T>*> nodes;
    nodes.push(root);
    nodes.push(nullptr); // dummy node as separator of levels
    TreeNode<T>* first;
    TreeNode<T>* prev = nullptr;
    while (!nodes.empty()) {
        TreeNode<T>* curNode = nodes.front();
        nodes.pop();
        if (curNode == nullptr) {
            listOfFL.push_back(first);
            // here if equal, then this is an edge case
            if (prev != first) {
                listOfFL.push_back(prev);
            }
            if (nodes.empty()) {
                break;
            }
            nodes.push(nullptr); // dummy node as separator of levels
        }
        else {
            if (prev == nullptr) {
                // dummy node as separator and start of new level
                first = curNode;
            }

            if (curNode->left != nullptr) {
                nodes.push(curNode->left);
            }
            if (curNode->right != nullptr) {
                nodes.push(curNode->right);
            }
        }
        prev = curNode;
    }
}

// ********************************************************************************
// Test
// ********************************************************************************
void TestCasesOfFirstAndLastOfEachLevelOfTree()
{
    std::vector<int> testInput{ 1 };
    TreeNode<int>* rootBFS = ConstructTreeOnSortedValueBFS(testInput);
    assert(rootBFS != nullptr);

    std::vector<TreeNode<int>*> result;
    GetFirstAndLastOfEachLevelOfTree(rootBFS, result);
    assert(result.size() == 1);
    assert(*result[0]->data == 1);
    DeleteTree(&rootBFS);

    testInput = { 1, 2 };
    rootBFS = ConstructTreeOnSortedValueBFS(testInput);
    assert(rootBFS != nullptr);
    result.clear();
    GetFirstAndLastOfEachLevelOfTree(rootBFS, result);
    assert(result.size() == 2);
    assert(*result[0]->data == 2);
    assert(*result[1]->data == 1);
    DeleteTree(&rootBFS);

    testInput = { 1, 2, 3 };
    rootBFS = ConstructTreeOnSortedValueBFS(testInput);
    assert(rootBFS != nullptr);
    result.clear();
    GetFirstAndLastOfEachLevelOfTree(rootBFS, result);
    assert(result.size() == 3);
    assert(*result[0]->data == 2);
    assert(*result[1]->data == 1);
    assert(*result[2]->data == 3);
    DeleteTree(&rootBFS);

    testInput = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    rootBFS = ConstructTreeOnSortedValueBFS(testInput);
    assert(rootBFS != nullptr);
    result.clear();
    GetFirstAndLastOfEachLevelOfTree(rootBFS, result);
    assert(result.size() == 7);
    // Tree:
    // 6
    // 3, 8
    // 1, 4, 7, 9
    // 2, 5, 10
    assert(*result[0]->data == 6);
    assert(*result[1]->data == 3);
    assert(*result[2]->data == 8);
    assert(*result[3]->data == 1);
    assert(*result[4]->data == 9);
    assert(*result[5]->data == 2);
    assert(*result[6]->data == 10);
    DeleteTree(&rootBFS);

}

Wednesday 16 September 2015

BST - Return the Sum of Each Level (Amazon Interview Question)

1. Problem Description

- AndreasVolcenstein 18 days ago in United States | Report Duplicate | Flag ".

2. C++ Implementation
// ********************************************************************************
// Implementation
//     - Breadth first
//     - Use null node as the dummy node to separate the levels
// ********************************************************************************
#include <cassert>
#include <memory>
#include <queue>
#include <stack>
#include <vector>

template<typename T>
struct TreeNode
{
    TreeNode(const T& d)
    : data(new T(d)), left(nullptr), right(nullptr)
    {}
    ~TreeNode()
    {
        std::shared_ptr<T>().swap(data);
    }

    std::shared_ptr<T> data;
    TreeNode* left;
    TreeNode* right;
};

template<typename T>
struct TreeConstructionBFS
{
    TreeConstructionBFS()
    {}

    TreeConstructionBFS(TreeNode<T>* p, bool left, int s, int e)
        : parent(p), isLeftChild(left), start(s), end(e)
    {}

    TreeNode<T>*    parent = nullptr;
    bool            isLeftChild = false;
    int             start = 0;
    int             end = -1;
};

// Free the resource
template<typename T>
void DeleteTree(TreeNode<T>** root)
{
    TreeNode<T>* curNode = *root;
    if (curNode != nullptr) {
        TreeNode<T>* left = curNode->left;
        TreeNode<T>* right = curNode->right;
        delete curNode;
        curNode = nullptr;
        DeleteTree(&left);
        DeleteTree(&right);
    }
}

// Construct BST based on sorted input via BFS
template<typename T>
TreeNode<T>* ConstructTreeOnSortedValueBFS(const std::vector<T>& input)
{
    if (input.empty()) {
        return nullptr;
    }

    const int len = input.size();
    int index = len >> 1;
    TreeNode<T>* root = new TreeNode<T>(input[index]);
    std::queue<TreeConstructionBFS<T>> nodesToBuild;
    nodesToBuild.push(TreeConstructionBFS<T>(root, true, 0, index - 1));
    nodesToBuild.push(TreeConstructionBFS<T>(root, false, index + 1, len - 1));

    while (!nodesToBuild.empty()) {
        const TreeConstructionBFS<T>& curCon = nodesToBuild.front();
        if (curCon.start > curCon.end) {
            if (curCon.isLeftChild) {
                curCon.parent->left = nullptr;
            }
            else {
                curCon.parent->right = nullptr;
            }
        }
        else {
            index = (curCon.start + curCon.end) >> 1;
            TreeNode<T>* tempNode = new TreeNode<T>(input[index]);
            if (curCon.isLeftChild) {
                curCon.parent->left = tempNode;
            }
            else {
                curCon.parent->right = tempNode;
            }

            nodesToBuild.push(TreeConstructionBFS<T>(tempNode, 
                                                     true,
                                                     curCon.start,
                                                     index - 1));
            nodesToBuild.push(TreeConstructionBFS<T>(tempNode,
                                                     false,
                                                     index + 1,
                                                     curCon.end));
        }
        nodesToBuild.pop();
    }

    return root;
}

// Implementation
template<typename T>
void GetSumOfEachLevelOfTree(TreeNode<T>* root, std::vector<T>& listOfLL)
{
    if (root == nullptr) {
        return;
    }

    std::queue<TreeNode<T>*> nodes;
    nodes.push(root);
    nodes.push(nullptr); // dummy node as separator of level
    T sum(0);
    while (!nodes.empty()) {
        const TreeNode<T>* curNode = nodes.front();
        nodes.pop();
        if (curNode == nullptr) {
            listOfLL.push_back(sum);
            sum = 0;
            if (nodes.empty()) {
                break;
            }
            nodes.push(nullptr); // dummy node as separator of level
        }
        else {
            sum += *curNode->data;
            if (curNode->left != nullptr) {
                nodes.push(curNode->left);
            }
            if (curNode->right != nullptr) {
                nodes.push(curNode->right);
            }
        }
    }
}

// ********************************************************************************
// Test
// ********************************************************************************
void TestCasesOfSumOfEachLevelOfTree()
{
    std::vector<int> testInput{ 1 };
    TreeNode<int>* rootBFS = ConstructTreeOnSortedValueBFS(testInput);
    assert(rootBFS != nullptr);

    std::vector<int> result;
    GetSumOfEachLevelOfTree(rootBFS, result);
    assert(result.size() == 1);
    assert(result[0] == 1);
    DeleteTree(&rootBFS);

    testInput = {1, 2};
    rootBFS = ConstructTreeOnSortedValueBFS(testInput);
    assert(rootBFS != nullptr);
    result.clear();
    GetSumOfEachLevelOfTree(rootBFS, result);
    assert(result.size() == 2);
    assert(result[0] == 2);
    assert(result[1] == 1);
    DeleteTree(&rootBFS);

    testInput = { 1, 2, 3 };
    rootBFS = ConstructTreeOnSortedValueBFS(testInput);
    assert(rootBFS != nullptr);
    result.clear();
    GetSumOfEachLevelOfTree(rootBFS, result);
    assert(result.size() == 2);
    assert(result[0] == 2);
    assert(result[1] == 4);
    DeleteTree(&rootBFS);

    testInput = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    rootBFS = ConstructTreeOnSortedValueBFS(testInput);
    assert(rootBFS != nullptr);
    result.clear();
    GetSumOfEachLevelOfTree(rootBFS, result);
    assert(result.size() == 4);
    assert(result[0] == 6); // 6
    assert(result[1] == 11);// 3, 8
    assert(result[2] == 21); // 1, 4, 7, 9 
    assert(result[3] == 17);// 2, 5, 10
    DeleteTree(&rootBFS);
}

BST - Find Next In-Order Value (Facebook Interview Question)

1. Problem Description
This is a Facebook interview question for software engineer from careercup. Here is the original thread,
"
Find the in-order successor of a node in BST
Kiara 2 months ago in United States Report Duplicate | Flag "

2. Analysis
The following picture shows the cases of the in-order successor of node "X".
Node X's in-order success in BST







































3. C++ Implementation
// ********************************************************************************
// Implementation
// ********************************************************************************
#include <cassert>
#include <memory>
#include <queue>
#include <stack>
#include <vector>

template<typename T>
struct TreeNode
{
    TreeNode(const T& d)
    : data(new T(d)), left(nullptr), right(nullptr)
    {}
    ~TreeNode()
    {
        std::shared_ptr<T>().swap(data);
    }

    std::shared_ptr<T> data;
    TreeNode* left;
    TreeNode* right;
};

template<typename T>
struct TreeConstructionBFS
{
    TreeConstructionBFS()
    {}

    TreeConstructionBFS(TreeNode<T>* p, bool left, int s, int e)
        : parent(p), isLeftChild(left), start(s), end(e)
    {}

    TreeNode<T>*    parent = nullptr;
    bool            isLeftChild = false;
    int             start = 0;
    int             end = -1;
};

template<typename T>
struct TreeConstructionDFS
{
    TreeConstructionDFS()
    {}

    TreeConstructionDFS(TreeNode<T>** n, int s, int e)
        : node(n), start(s), end(e)
    {}

    TreeNode<T>**   node = nullptr;
    int             start = 0;
    int             end = -1;
};

// Create BST based on sorted input via BFS
template<typename T>
TreeNode<T>* ConstructTreeOnSortedValueBFS(const std::vector<T>& input)
{
    if (input.empty()) {
        return nullptr;
    }

    const int len = input.size();
    int index = len >> 1;
    TreeNode<T>* root = new TreeNode<T>(input[index]);
    std::queue<TreeConstructionBFS<T>> nodesToBuild;
    nodesToBuild.push(TreeConstructionBFS<T>(root, true, 0, index - 1));
    nodesToBuild.push(TreeConstructionBFS<T>(root, false, index + 1, len - 1));

    while (!nodesToBuild.empty()) {
        const TreeConstructionBFS<T>& curCon = nodesToBuild.front();
        if (curCon.start > curCon.end) {
            if (curCon.isLeftChild) {
                curCon.parent->left = nullptr;
            }
            else {
                curCon.parent->right = nullptr;
            }
        }
        else {
            index = (curCon.start + curCon.end) >> 1;
            TreeNode<T>* tempNode = new TreeNode<T>(input[index]);
            if (curCon.isLeftChild) {
                curCon.parent->left = tempNode;
            }
            else {
                curCon.parent->right = tempNode;
            }

            nodesToBuild.push(TreeConstructionBFS<T>(tempNode,
                                                     true,
                                                     curCon.start,
                                                     index - 1));
            nodesToBuild.push(TreeConstructionBFS<T>(tempNode,
                                                     false,
                                                     index + 1,
                                                     curCon.end));
        }
        nodesToBuild.pop();
    }

    return root;
}

// Create BST based on sorted input via DFS
template<typename T>
TreeNode<T>* ConstructTreeOnSortedValueDFS(const std::vector<T>& input)
{
    if (input.empty()) {
        return nullptr;
    }

    const int len = input.size();
    int index = len >> 1;
    TreeNode<T>* root = new TreeNode<T>(input[index]);
    std::stack<TreeConstructionDFS<T>> nodesToBuild;
    nodesToBuild.push(TreeConstructionDFS<T>(&root->left, 0, index - 1));
    nodesToBuild.push(TreeConstructionDFS<T>(&root->right, index + 1, len - 1));

    while (!nodesToBuild.empty()) {
        const TreeConstructionDFS<T>& curCon = nodesToBuild.top();
        if (curCon.start > curCon.end) {
            *(curCon.node) = nullptr;
            nodesToBuild.pop();
        }
        else {
            index = (curCon.start + curCon.end) >> 1;
            TreeNode<T>* tempNode = new TreeNode<T>(input[index]);
            *(curCon.node) = tempNode;

            TreeConstructionDFS<T> left(&tempNode->left,
                                        curCon.start,
                                        index - 1);
            TreeConstructionDFS<T> right(&tempNode->right,
                                         index + 1,
                                         curCon.end);
            nodesToBuild.pop();
            nodesToBuild.push(left);
            nodesToBuild.push(right);
        }
    }

    return root;
}

// Free the resource
template<typename T>
void DeleteTree(TreeNode<T>** root)
{
    TreeNode<T>* curNode = *root;
    if (curNode != nullptr) {
        TreeNode<T>* left = curNode->left;
        TreeNode<T>* right = curNode->right;
        delete curNode;
        curNode = nullptr;
        DeleteTree(&left);
        DeleteTree(&right);
    }
}

// Find "X" in BST
template<typename T>
bool FindPath(TreeNode<T>* root, const T& val, std::stack<TreeNode<T>*>& path)
{
    TreeNode<T>* curNode = root;
    std::stack<TreeNode<T>*> result;
    bool found = false;
    while (curNode != nullptr) {
        result.push(curNode);

        const T& curVal = *curNode->data.get();
        if (curVal == val) {
            found = true;
            break;
        }
        if (curVal > val) {
            if (curNode->left == nullptr) {
                break;
            }
            curNode = curNode->left;
        }
        else {
            if (curNode->right == nullptr) {
                break;
            }
            curNode = curNode->right;
        }

    }
    if (found) {
        path.swap(result);
    }

    return found;
}

// Find the leftest node given a root
template<typename T>
std::shared_ptr<T> FindLeftestNode(TreeNode<T>* root)
{
    TreeNode<T>* curNode = root;
    while (curNode->left != nullptr) {
        curNode = curNode->left;
    }

    return curNode->data;
}

template<typename T>
std::shared_ptr<T> NextInOrder(TreeNode<T>* root, const T& val)
{
    std::stack<TreeNode<T>*> path;
    if (!FindPath(root, val, path)) {
        return std::shared_ptr<T>();
    }

    TreeNode<T>* curNode = path.top();
    assert(*curNode->data.get() == val);
    if (curNode->right != nullptr) {
        // Case 1
        return FindLeftestNode(curNode->right);
    }

    path.pop();
    // Case 2
    TreeNode<T>* parentNode;
    while (!path.empty())
    {
        parentNode = path.top();
        if (parentNode->left == curNode) {
            return parentNode->data;
        }

        curNode = parentNode;
        path.pop();
    }
    // Case 2: can't find Pn
    return std::shared_ptr<T>();
}

// ********************************************************************************
// Test
// ********************************************************************************
void TestCasesOfNextInOrder()
{
    const std::vector<int> testInput{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    TreeNode<int>* rootBFS = ConstructTreeOnSortedValueBFS(testInput);
    assert(rootBFS != nullptr);

    auto nextInOrder = NextInOrder(rootBFS, 0);
    assert(nextInOrder.get() == nullptr);
    nextInOrder = NextInOrder(rootBFS, 1);
    assert(*nextInOrder == 2);
    nextInOrder = NextInOrder(rootBFS, 2);
    assert(*nextInOrder == 3);
    nextInOrder = NextInOrder(rootBFS, 3);
    assert(*nextInOrder == 4);
    nextInOrder = NextInOrder(rootBFS, 4);
    assert(*nextInOrder == 5);
    nextInOrder = NextInOrder(rootBFS, 5);
    assert(*nextInOrder == 6);
    nextInOrder = NextInOrder(rootBFS, 6);
    assert(*nextInOrder == 7);
    nextInOrder = NextInOrder(rootBFS, 7);
    assert(*nextInOrder == 8);
    nextInOrder = NextInOrder(rootBFS, 8);
    assert(*nextInOrder == 9);
    nextInOrder = NextInOrder(rootBFS, 9);
    assert(*nextInOrder == 10);
    nextInOrder = NextInOrder(rootBFS, 10);
    assert(nextInOrder.get() == nullptr);
    nextInOrder = NextInOrder(rootBFS, 11);
    assert(nextInOrder == nullptr);


    TreeNode<int>* rootDFS = ConstructTreeOnSortedValueDFS(testInput);
    assert(rootDFS != nullptr);
    nextInOrder = NextInOrder(rootDFS, 0);
    assert(nextInOrder.get() == nullptr);
    nextInOrder = NextInOrder(rootDFS, 1);
    assert(*nextInOrder == 2);
    nextInOrder = NextInOrder(rootDFS, 2);
    assert(*nextInOrder == 3);
    nextInOrder = NextInOrder(rootDFS, 3);
    assert(*nextInOrder == 4);
    nextInOrder = NextInOrder(rootDFS, 4);
    assert(*nextInOrder == 5);
    nextInOrder = NextInOrder(rootDFS, 5);
    assert(*nextInOrder == 6);
    nextInOrder = NextInOrder(rootDFS, 6);
    assert(*nextInOrder == 7);
    nextInOrder = NextInOrder(rootDFS, 7);
    assert(*nextInOrder == 8);
    nextInOrder = NextInOrder(rootDFS, 8);
    assert(*nextInOrder == 9);
    nextInOrder = NextInOrder(rootDFS, 9);
    assert(*nextInOrder == 10);
    nextInOrder = NextInOrder(rootDFS, 10);
    assert(nextInOrder.get() == nullptr);
    nextInOrder = NextInOrder(rootDFS, 11);
    assert(nextInOrder == nullptr);

    DeleteTree(&rootBFS);
    DeleteTree(&rootDFS);
}

Monday 7 September 2015

Functional Programming - Divide Array into Two Equal Parts (Google Interview Question)

1. Problem Description
This is a Google interview question for software engineer from careercup. Here is the original description,


- smarthbehl 10 days ago in United States | Report Duplicate | Flag ".

2. Analysis and Solution
It is a combination problem. A problem like given N cards and pick up any half of cards and find out the one combination with the sum closest to the half of sum of all. In this problem we have to differentiate if N is odd or even. If N = 2m, then the number of combination is m!/N!. Anf if N = 2*m+1, then the number of combination is m!/N! too.

Another way of thinking of this problem is regarding it as an optimization problem. 
    - Objective function: Min(lambda1*X1+lamda2*X2 + ... + lamdaN*XN - HalfOfSum)
    - Where lamda(i) either equal to 0 or 1
       and Sigma(lamda(i)) = m

These two are identical in essence. Here I am going to propose how to solve it via functional programming in C++.
    - n < m,
        * F(n) = F(n-1) + lamda(n)*Xn, where lamda(n) = 1
    - n = m
        * check the sum of F(n) with half of the value of sum of all. Take the min.
        * Exhaust other options of Xn. (in this case n is still equal to m and repeat this case)
        * Flip previous lamda(n-1) = 0 and exhaust Xn-1. n != m anymore and repeat the whole.

In order to limit the case of Xn, Xn-1 ...., we will sort the array first. If we found the F(n) (n = m) and its sum is over the the min value we recorded so far, then skipped the rest Xn. Because it is sorted any smaller value is replaced with larger one and this does not affect the optimization process.

Another one if we find a solution, for instance a F(n) (n = m) and its value is equal to exactly half of the value of sum of all, then we can stop because one of global solution is found. In my implementation there is a special case that all the numbers are integer. Therefore if the difference is less than 1 we can confirm that a global solution is found.     

3. C++ Implementation
// ********************************************************************************
// Implementation
// ********************************************************************************
#include <algorithm>
#include <numeric>
#include <stack>
#include <vector>

using DataArray = std::vector<unsigned int>;
using ResultStack = std::stack<size_t>;

enum class Action
{
    STOP,
    CONTINUE,
    FOUND
};

Action DivideTwoPartsWithEqualSum(const DataArray& input,
                                const size_t last_index,
                                const double sum_of_part,
                                const size_t size_of_part,
                                const size_t size_of_all,
                                ResultStack& result,
                                size_t& result_size,
                                double& sumOfResult,
                                ResultStack& curBestResult,
                                double& sumOfCurBestResult)
{
    if (result_size == size_of_part) {
        if (fabs(sumOfResult - sum_of_part) < fabs(sumOfCurBestResult - sum_of_part)) {
            // track the min solution
            curBestResult = result;
            sumOfCurBestResult = sumOfResult;
        }
        if (fabs(sumOfCurBestResult - sum_of_part) < 1.0) {
            // found the best solution;
            return Action::FOUND;
        }
        else if (sumOfResult > sum_of_part) {
            // stop here because the rest of combination can't be smaller
            return Action::STOP;
        }

        return Action::CONTINUE;
    }

    Action act = Action::CONTINUE;
    const size_t startIndex = result.top() + 1;
    const size_t endIndex = size_of_all - (size_of_part - result_size) + 1;
    for (size_t index = startIndex; index < endIndex; ++index) {
        // select lamda(i) and push in
        result.push(index);
        ++result_size;
        sumOfResult += input[index];
        act = DivideTwoPartsWithEqualSum(input, last_index, sum_of_part,
                                         size_of_part, size_of_all,
                                         result, result_size, sumOfResult,
                                         curBestResult, sumOfCurBestResult);

        if (act == Action::FOUND) {
            break;
        }
        // flip lamda(i) and pop out 
        result.pop();
        --result_size;
        sumOfResult -= input[index];
        if (act == Action::STOP) {
            act = Action::CONTINUE;
        }
    }

    return act;
}

double DivideToTwoPartsWithEqualSum(const DataArray& input,
                                    DataArray& result)
{
    if (input.empty()) {
        return -1.0;
    }

    const size_t len = input.size();
    const size_t size_of_part = len >> 1;
    const double sum_of_all = std::accumulate(input.begin(), input.end(), 0.0);

    const double sum_of_part = sum_of_all/2;
    const size_t last_index = (len & 1) > 0 ? (size_of_part + 2) : (size_of_part + 1);
    DataArray inputCopy(input);
    ResultStack tempResult;
    size_t size_of_stack;
    double sum_of_stack;
    ResultStack bestResult;
    double sumOfBestResult;
    std::sort(inputCopy.begin(), inputCopy.end()); // sort
    for (size_t index = 0; index < last_index; ++index) {
        tempResult.push(index);
        size_of_stack = 1;
        sum_of_stack = inputCopy[index];
        if (DivideTwoPartsWithEqualSum(inputCopy, last_index,
                                       sum_of_part, size_of_part, len,
                                       tempResult, size_of_stack,
                                       sum_of_stack, bestResult, 
                                       sumOfBestResult) == Action::FOUND) {
            break;
        }
        tempResult.pop();
    }

    result.clear();
    result.reserve(size_of_part);
    while (!bestResult.empty())
    {
        result.push_back(inputCopy[bestResult.top()]);
        bestResult.pop();
    }

    return sumOfBestResult;
}

// ********************************************************************************
// Test
// ********************************************************************************
void TestCases
{
    DataArray result;
    // solution: 1, 8, 9
    assert(DivideToTwoPartsWithEqualSum(DataArray{ 1, 2, 3, 6, 8, 9, 7 }, result) == 18.0);
    // solution: 5, 7, 62
    assert(DivideToTwoPartsWithEqualSum(DataArray{ 5, 7, 50, 8, 9, 62 }, result) == 74);
    // solution: 10, 20
    assert(DivideToTwoPartsWithEqualSum(DataArray{ 1, 10, 11, 18, 20 }, result) == 30);
    // solution: 1, 10, 13
    assert(DivideToTwoPartsWithEqualSum(DataArray{ 1, 7, 8, 9, 10, 13 }, result) == 24);
}