Tag Archives: java script

Zigzag Conversion

[tabby title=”Task”]

The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P   A   H   N
A P L S I I G
Y   I   R

And then read line by line: "PAHNAPLSIIGYIR"

Write the code that will take a string and make this conversion given a number of rows:

string convert(string s, int numRows);

Example 1:

Input:

 s = "PAYPALISHIRING", numRows = 3

Output:

 "PAHNAPLSIIGYIR"

Example 2:

Input:

 s = "PAYPALISHIRING", numRows = 4

Output:

 "PINALSIGYAHRPI"

Explanation:

P     I    N
A   L S  I G
Y A   H R
P     I

Example 3:

Input:

 s = "A", numRows = 1

Output:

 "A"

 

This problem was taken from Leet code, ZigZag conversion

 

[tabby title=”Solution”]

It’s take the first example string: “PAYPALISHIRING

An array representation of the string would be done by pushing each character into the array.

Then if we want to iterate through this array in zig zag pattern with 3 rows, it will look like this:

 

Then, we have to create 3 arrays representing the 3 rows as follows:

Dots represent empty strings which we have to ignore before concatenating all 3 rows, convert them to string and this is the answer to this problem.

But how to create the loop to traverse through the zig zag pattern (figure 1) ?

  • first we set up `headingDown` flag to determine if we are going down or up
  • each time when the row reaches numRows we are flipping the value of headingDown
  • when headingDown is false (meaning that we are heading up) we have to do it diagonally: row — , col ++
  • when row become 0 we are flipping again headingDown and it becomes true again: row ++ and we keep storing values of every character we traversed in the result array.
 /**
 * @param {string} s
 * @param {number} numRows
 * @return {string}
 */
var convert = function(s, numRows) {

    // if we don't have any rows or there is an empty string just return back empty string
    if(s.length === 0 || numRows === 0) 
        return '';

    // if rows are numRows is just one, we return the same string
    if(numRows === 1) {
        return s;
    }
    
    var l = s.length;
    // put the string into single dimension array to iterate through
    var arr = s.split('');
    
    var rowsArray = [];
    var row = 0;
    var col = 0;
    var headingDown = true; // this determines if the cursor is heading down in the same column, or up leaping to the next column (dizgonal)

    // instantiate numRows arrays to store values of each row
    for(var i = 0; i < numRows; i ++) {
        rowsArray[i] = [];
    }

    // loop through each element in arr and fill rowsArray ()
    for(var i = 0; i < l; i ++) {
        rowsArray[row][col] = arr[i];
        if(headingDown) {
            row ++;
        }
        else {
            row --;
            col ++;
        }

        
        if(row == numRows -1) {
            headingDown = false;
        } else if(row == 0) {
            headingDown = true;
        }
        
    }

    // Read 2D array and assemble the string
    var result = [];
    for(var i = 0; i < numRows; i ++) {
        for(var j = 0; j < rowsArray[i].length; j ++) {
            if(typeof rowsArray[i][j] != 'undefined') {
                result.push(rowsArray[i][j]);
            }
        }
    }
    return result.join('');
};

convert('PAYPALISHIRING', 3);
convert('AB', 1);
//convert('ABC', 1);

 

How can we optimize this ?

the above example is good to read but not a good practical example. First we don’t need two dimensional array to store characters for each row. We could replace this with string array and just keep adding characters till we reached the end of the string. This way we also don’t need to keep track of cols

/**
 * @param {string} s
 * @param {number} numRows
 * @return {string}
 */
var convert = function(s, numRows) {

    // if we don't have any rows or there is an empty string just return back empty string
    if(s.length === 0 || numRows === 0) 
        return '';

    // if rows are numRows is just one, we return the same string
    if(numRows === 1) {
        return s;
    }
    
    var l = s.length;
    // put the string into single dimension array to iterate through
    var arr = s.split('');
    
    var left = 0;
    var arrStrings = [];
    var row = 0;
    var col = 0;
    var headingDown = true; // this determines if the cursor is heading down in the same column, or up leaping to the next column (dizgonal)

    // instantiate numRows arrays to store values of each row
    for(var i = 0; i < numRows; i ++) {
        arrStrings[i] = '';
    }

    
    // loop through each element in arr and fill arrStrings ()
    for(var i = 0; i < l; i ++) {
        //arrStrings[row][col] = arr[i];
        if(headingDown) {
            arrStrings[row] += arr[i];
            row ++;
        }
        else {
            arrStrings[row] += arr[i];
            row --;
            col ++;
        }

        
        if(row == numRows -1) {
            headingDown = false;
        } else if(row == 0) {
            headingDown = true;
        }
        
    }

    var result = '';
    // combine all strings and return as one 
    for(var i = 0; i < numRows; i ++) {
        result += arrStrings[i];
    }
        
    return result;
};

 

[tabbyending]

Simple use of Java Script spread operator

Converting array into object

// The array
var numbers = [1,2,3];


var obj = {...numbers }

console.log(obj)
// result: {0:1, 1:2, 2:3}

 

Expanding object with new parameter

// The array
var person = {
  name: 'Jhon'
}

var obj = {...person, age: 23 }

console.log(obj)
// expected person to be: {name: 'John', age:23 }

 

Getting sum of an array

function sum(x, y, z) {
  return x + y + z;
}

const numbers = [1, 2, 3];

console.log(sum(...numbers));
// resunt: 6

 

Longest Common Substring

[tabby title=”Task”]

Given two strings text1 and text2, return the length of their longest common subsequenceIf there is no common subsequence, return 0.

subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.

  • For example, "ace" is a subsequence of "abcde".

common subsequence of two strings is a subsequence that is common to both strings.

 

Example 1:

Input:

 text1 = "abcde", text2 = "ace" 

Output:

 3  

Explanation:

 The longest common subsequence is "ace" and its length is 3.

Example 2:

Input:

 text1 = "abc", text2 = "abc"

Output:

 3

Explanation:

 The longest common subsequence is "abc" and its length is 3.

Example 3:

Input:

 text1 = "abc", text2 = "def"

Output:

 0

Explanation:

 There is no such common subsequence, so the result is 0.

 

Constraints:

  • 1 <= text1.length, text2.length <= 1000
  • text1 and text2 consist of only lowercase English characters.

This problem was taken from Leetcode Longest Common Subsequence

 

[tabby title=”Solution”]

Dynamic programming with memoization.

We create a matrix to store (memoize) the response from previous calculations so we won’t re-calculate them again.

We are starting from the first row comparing every character from column 1 with the first character from row one.

There are two cases:

  • either the character match, then we add 1 and add it with the value from the diagonal to the left of the cell where we are.

Longest Common Substring Step 1

  • the characters don’t match, then we get the MAX of the value above current cell  and the value to the left of the current cell.

Longest Common Substring Step 2

Here again c int the column (first string) matches c in the row (the second string)

so we get the value of last comparison (to the left and up diagonal of the current cell)  which is 1 and add 1 again since characters match.

Longest Common Substring 3

and keep going till we reach the end of both strings which is the answer.

 

Longest Common Substring 4

 

/**
 * @param {string} text1
 * @param {string} text2
 * @return {number}
 */
var longestCommonSubsequence = function(text1, text2) {
    var txt1 = text1.split('');
    var txt2 = text2.split('');

    txt1.unshift('0');
    txt2.unshift('1');

    var l1 = txt1.length;
    var l2 = txt2.length;

    var matrix = [];
    for(var i = 0; i < l2; i ++) {
        matrix[i] = new Array(l1).fill(0);
    }

    var maxCommon = 0;
    
    for(var row = 0; row < l2; row ++) {
        for(var col = 0; col < l1; col ++) {
            var last = 0;

            if(txt1[col] == txt2[row]) {
                var previousDiagonalRowVal = row == 0 || col == 0  ? 0 : matrix[row - 1][col - 1];
                last =  1 + previousDiagonalRowVal;
            }
            else {
                var prevUp = row == 0 ?  0 : matrix[row - 1][col];
                var prevLeft = col == 0 ? 0 : matrix[row][col - 1];               
                last = Math.max(prevUp, prevLeft);
            }
            matrix[row][col] = last;
            maxCommon = last > maxCommon ? last : maxCommon;
    
        }
    }    
    return maxCommon;
};

var text1 = "abcde", text2 = "ace";
var r = longestCommonSubsequence(text1, text2);
console.log(">>", r);

[tabbyending]

Copy List with Random Pointer

[tabby title=”Task”]

 

A linked list of length n is given such that each node contains an additional random pointer, which could point to any node in the list, or null.

Construct a deep copy of the list. The deep copy should consist of exactly n brand new nodes, where each new node has its value set to the value of its corresponding original node. Both the next and random pointer of the new nodes should point to new nodes in the copied list such that the pointers in the original list and copied list represent the same list state. None of the pointers in the new list should point to nodes in the original list.

For example, if there are two nodes X and Y in the original list, where X.random --> Y, then for the corresponding two nodes x and y in the copied list, x.random --> y.

Return the head of the copied linked 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) that the random pointer points to, or null if it does not point to any node.

Your code will only be given the head of the original linked list.

 

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]]

 

Constraints:

  • 0 <= n <= 1000
  • -104 <= Node.val <= 104
  • Node.random is null or is pointing to some node in the linked list.

This problem was taken from https://leetcode.com/problems/copy-list-with-random-pointer/

[tabby title=”Solution”]

 

Brute force using tree traversal

 

/**
 * // Definition for a Node.
 * function Node(val, next, random) {
 *    this.val = val;
 *    this.next = next;
 *    this.random = random;
 * };
 */

/**
 * @param {Node} head
 * @return {Node}
 */
var copyRandomList = function(head) {


    function dfsTraverse(node, visited={}) {
        if(!node) {
            return null;
        }
        
        // if a new node is created, return it. Otherwise you will fall into circular loops
        if(node?.clone) {
            return node?.clone;    
        }
        
        var newNode = new Node(node?.val, null, null);
        node.clone = newNode;
        var next = dfsTraverse(node?.next);
        var random = dfsTraverse(node?.random);

        newNode.next = next;
        newNode.random = random;
        return newNode;
    }

    var result = dfsTraverse(head);
    return result;
};

function Node(val, next, random) {
    this.val = val;
    this.next = next;
    this.random = random;
}
;// [1,null],[2,0],[3,1]

var nodes = {};
nodes['1'] = new Node(1,null,null);
nodes['2'] = new Node(2,null,null);
nodes['3'] = new Node(3,null,null);

nodes['1'].next = nodes['2'];
nodes['1'].random = null;

nodes['2'].next = nodes['3'];
nodes['2'].random = nodes['1'];

nodes['3'].next = null;
nodes['3'].random = nodes['2'];

//console.log("root");
//console.log(nodes['7']);
var result = copyRandomList(nodes['1']);
console.log(result);

 

 

More elegant solution

 

/**
 * // Definition for a Node.
 * function Node(val, next, random) {
 *    this.val = val;
 *    this.next = next;
 *    this.random = random;
 * };
 */

/**
 * @param {Node} head
 * @return {Node}
 */
var copyRandomList = function(head) {
  let cur = head;
  const copy = new Map();

  // add all new nodes and values for now
  while (cur) {
    copy.set(cur, new Node(cur.val));
    cur = cur.next;
  }
  
  cur = head;

  // iterate again and point curent node to the newly created nodes using the key 
  while (cur) {
    copy.get(cur).next = copy.get(cur.next) || null;
    copy.get(cur).random = copy.get(cur.random) || null;
    cur = cur.next;
  }
  
  return copy.get(head);
}


function Node(val, next, random) {
    this.val = val;
    this.next = next;
    this.random = random;
};


// [1,null],[2,0],[3,1]

var nodes = {};
nodes['1'] = new Node(1,null,null);
nodes['2'] = new Node(2,null,null);
nodes['3'] = new Node(3,null,null);

nodes['1'].next = nodes['2'];
nodes['1'].random = null;

nodes['2'].next = nodes['3'];
nodes['2'].random = nodes['1'];

nodes['3'].next = null;
nodes['3'].random = nodes['2'];


var result = copyRandomList(nodes['1']);
console.log(result);

 

 

[tabbyending]

Range Sum of BST

[tabby title=”Task”]

Given the root node of a binary search tree and two integers low and high, return the sum of values of all nodes with a value in the inclusive range [low, high].

 

Example 1:

Input:

 root = [10,5,15,3,7,null,18], low = 7, high = 15

Output:

 32

Explanation:

 Nodes 7, 10, and 15 are in the range [7, 15]. 7 + 10 + 15 = 32.

Example 2:

Input:

 root = [10,5,15,3,7,13,18,1,null,6], low = 6, high = 10

Output:

 23

Explanation:

 Nodes 6, 7, and 10 are in the range [6, 10]. 6 + 7 + 10 = 23.

 

Constraints:

  • The number of nodes in the tree is in the range [1, 2 * 104].
  • 1 <= Node.val <= 105
  • 1 <= low <= high <= 105
  • All Node.val are unique.

This problem was taken from https://leetcode.com/problems/range-sum-of-bst/

 

[tabby title=”Solution”]

 

DFS Solution

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} low
 * @param {number} high
 * @return {number}
 */
var rangeSumBST = function(root, low, high) {
    if(!root) {
        return;
    }
    console.log(root.val);
    var queue = [root];
    var visited = {};
    var result = 0.0;    

    function dfsTraverse(root, low, high) {
    
        var childNodes = [root?.left, root?.right];

        for(const childNode of childNodes) {
          if(childNode) {
            var val = childNode.val;
            console.log(val);
            dfsTraverse(childNode, low, high);            
          }
        }

    }

    dfsTraverse(root, low, high);
    return result;
};


 function TreeNode(val, left, right) {
     this.val = (val===undefined ? 0 : val)
     this.left = (left===undefined ? null : left)
     this.right = (right===undefined ? null : right)
 }

const treeNode = new TreeNode(
    10,
    new TreeNode(
        5,
        new TreeNode(3),
        new TreeNode(7)
    ),
    new TreeNode(
        15,
        null,
        new TreeNode(18)
    )
)


rangeSumBST(treeNode, 7, 15);

 

BFS solution

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} low
 * @param {number} high
 * @return {number}
 */
var rangeSumBST = function(root, low, high) {
    if(!root) {
        return 0;
    }
    var queue = [root];
    var visited = {};
    var result = 0.0;    
    if(root.val >= low && root.val <= high) {
        result = root.val;
    }
    
    var leftPointer = 0;
    while(leftPointer <= queue.length) {
        var curentNode = queue[leftPointer];
        leftPointer ++;
        var childNodes = [curentNode?.left, curentNode?.right];
        
        for(const childNode of childNodes) {
            if(childNode) {
                console.log(childNode.val)
                if(childNode.val >= low && childNode.val <= high) {
                    result += childNode.val;
                }
                queue.push(childNode);
            }
        }
        
           
    }
    return result;
    
};

 

[tabbyending]

Graph traversal

The graph

The graph represent connections between airports. Nodes (vertices)  represent airports, and  edges represent flights.

BFS search (Breadth First Search)

Breadth-first Search (BFS) starts by pushing all of the direct children to a queue (first-in, first-out). It then visits each item in queue and adds the next layer of children to the back of the queue. Since one node could be visited multiple times causing infinite loop, we have to keep track of all visited nodes.

Using JavaScript Map

// DATA
const airports = 'PHX BKK OKC JFK LAX MEX EZE HEL LOS LAP LIM'.split(' ');

const routes = [
    ['PHX', 'LAX'],
    ['PHX', 'JFK'],
    ['JFK', 'OKC'],
    ['JFK', 'HEL'],
    ['JFK', 'LOS'],
    ['MEX', 'LAX'],
    ['MEX', 'BKK'],
    ['MEX', 'LIM'],
    ['MEX', 'EZE'],
    ['LIM', 'BKK'],
];


// The graph
const adjacencyList = new Map();

// Add node
function addNode(airport) {
    adjacencyList.set(airport, []);
}

// Add edge, undirected
function addEdge(origin, destination) {
    adjacencyList.get(origin).push(destination);
    adjacencyList.get(destination).push(origin);
}

// Create the Graph
airports.forEach(addNode);
routes.forEach(route => addEdge(route[0], route[1]));

console.log(adjacencyList);


function bfs(start, searchItem) {

    const visited = new Set();
    const queue = [start];


    while (queue.length > 0) {

        const airport = queue.shift(); // mutates the queue
        const destinations = adjacencyList.get(airport);


        for (const destination of destinations) {
            if (destination === searchItem)  {
                console.log(`BFS found a route to`, searchItem)
            }

            if (!visited.has(destination)) {
                visited.add(destination);
                queue.push(destination);
            }           
        }        
    }

}

bfs('PHX', 'BKK');

 

Using JavaScript object

// Data
var airports = {
    'PHX': ['LAX', 'JFK'],
    'BKK': ['MEX', 'LIM'],
    'OKC': ['JFK'],
    'JFK': ['LAX', 'PHX', 'OKC', 'HEL', 'LOS', 'EZE'],
    'LAX': ['PHX', 'JFK', 'MEX'],
    'MEX': ['LAX', 'EZE', 'BKK', 'LIM'],
    'EZE': ['JFK', 'MEX'],
    'HEL': ['JFK'],
    'LOS': ['JFK'],
    'LAP': [],
    'LIM': ['MEX', 'BKK']
};


function bfs(start, endDest) {
    var queue = [start];
    var visited = {};

    while(queue.length > 0) {
        var curentNodeVal = queue.shift();
        var childNodes = airports[curentNodeVal];
        for(const childNode of childNodes) {
            if(childNode === endDest) {
                console.log("BFS found a route to :", endDest);
            }            

            if(!visited[childNode]) {
                console.log(childNode);
                visited[childNode] = true;
                queue.push( childNode);          
            }
        }
    }
}


bfs('PHX', 'BKK');

 

DFS (Depth First Search)

Depth-first Search (DFS) will go as far into the graph as possible until it reaches a node without any children, at which point it backtracks and continues the process. The algorithm can be implemented with a recursive function that keeps track of previously visited nodes. If a node has not been visited, we call the function recursively.

Using JavaScript Map

// DATA
const airports = 'PHX BKK OKC JFK LAX MEX EZE HEL LOS LAP LIM'.split(' ');

const routes = [
    ['PHX', 'LAX'],
    ['PHX', 'JFK'],
    ['JFK', 'OKC'],
    ['JFK', 'HEL'],
    ['JFK', 'LOS'],
    ['MEX', 'LAX'],
    ['MEX', 'BKK'],
    ['MEX', 'LIM'],
    ['MEX', 'EZE'],
    ['LIM', 'BKK'],
];

// The graph
const adjacencyList = new Map();

// Add node
function addNode(airport) {
    adjacencyList.set(airport, []);
}

// Add edge, undirected
function addEdge(origin, destination) {
    adjacencyList.get(origin).push(destination);
    adjacencyList.get(destination).push(origin);
}

// Create the Graph
airports.forEach(addNode);
routes.forEach(route => addEdge(route[0], route[1]));

console.log(adjacencyList);



function dfs(start, visited = new Set()) {

    console.log(start)
    
    visited.add(start);

    const destinations = adjacencyList.get(start);

    for (const destination of destinations) {

        if (destination === 'BKK') { 
            console.log(`DFS found Bangkok`)
            return;
        }
        
        if (!visited.has(destination)) {
            dfs(destination, visited);
        }

    }

}

dfs('PHX');

Using JavaScript object

// Data
var airports = {
    'PHX': ['LAX', 'JFK'],
    'BKK': ['MEX', 'LIM'],
    'OKC': ['JFK'],
    'JFK': ['LAX', 'PHX', 'OKC', 'HEL', 'LOS', 'EZE'],
    'LAX': ['PHX', 'JFK', 'MEX'],
    'MEX': ['LAX', 'EZE', 'BKK', 'LIM'],
    'EZE': ['JFK', 'MEX'],
    'HEL': ['JFK'],
    'LOS': ['JFK'],
    'LAP': [],
    'LIM': ['MEX', 'BKK']
};


function dfs(start, endDest, visited = {}) {
        
    visited[start] = true;
    console.log(start);

    const destinations = airports[start];

    for(const destination of  destinations) {
        if (destination === endDest) { 
            console.log(`DFS found route to`, endDest);
        }

        if(!visited[destination]) {
            dfs(destination, endDest, visited);
        }
        
    }
}


dfs('PHX', 'BKK');

 

Moving Average from Data Stream

[tabby title=”Task”]

Given a stream of integers and a window size, calculate the moving average of all integers in the sliding window.

Implement the MovingAverage class:

  • MovingAverage(int size) Initializes the object with the size of the window size.
  • double next(int val) Returns the moving average of the last size values of the stream.

 

Example 1:

Input

["MovingAverage", "next", "next", "next", "next"]
[[3], [1], [10], [3], [5]]

Output

[null, 1.0, 5.5, 4.66667, 6.0]

Explanation

MovingAverage movingAverage = new MovingAverage(3);
movingAverage.next(1); // return 1.0 = 1 / 1
movingAverage.next(10); // return 5.5 = (1 + 10) / 2
movingAverage.next(3); // return 4.66667 = (1 + 10 + 3) / 3
movingAverage.next(5); // return 6.0 = (10 + 3 + 5) / 3

 

Constraints:

  • 1 <= size <= 1000
  • -105 <= val <= 105
  • At most 104 calls will be made to next.

[tabby title=”Solution”]

/**
 * @param {number} size
 */
var MovingAverage = function(size) {
    this.n = size;
    this.queue = [];
    this.average = 0.0;
};

/** 
 * @param {number} val
 * @return {number}
 */
MovingAverage.prototype.next = function(val) {
    var removedVal;
    if(this.queue.length >= this.n) {
        removedVal = this.queue.shift();
        this.average = this.average - removedVal;
    }

    this.queue.push(val);
    
    this.average += val;
    console.log(this.average / this.queue.length);
    return this.average / this.queue.length;
};


var movingAverage = new MovingAverage(3);
movingAverage.next(1); // return 1.0 = 1 / 1
movingAverage.next(10); // return 5.5 = (1 + 10) / 2
movingAverage.next(3); // return 4.66667 = (1 + 10 + 3) / 3
movingAverage.next(5); // return 6.0 = (10 + 3 + 5) / 3

 

[tabbyending]

Heaps or priority queues in Java Script

Still work in progress …

 

Part I Heapify …

 

heap-sorting

 

Part II sort and heapify

We start swapping values and heapify each time starting from 0 to the length of i

function heapSort(arr) {

    function maxHeapify(arr, i, N) {
        var leftChild = i * 2 + 1;
        var rightChild = i * 2 + 2;
        var largest = i;
    
        if(leftChild < N && arr[leftChild] > arr[largest]) {
            largest = leftChild;
        }
    
        if(rightChild < N && arr[rightChild] > arr[largest]) {
            largest = rightChild;
        }
    
        if(largest != i) {
            var temp = arr[i];
            arr[i] = arr[largest];
            arr[largest] = temp;
            maxHeapify(arr, largest, N);
        }
    }
    
    // CREATE A HEAP
    for(var i = parseInt(arr.length / 2 - 1); i >= 0; i--) {
        maxHeapify(arr, i, arr.length);
    }
    
    console.log("heap represented in array: ", arr);
    
    // SORT THE ARRAY
    for(var i =  arr.length - 1; i >= 0; i --) {
        var temp = arr[0];
        arr[0] = arr[i];
        arr[i] = temp;
    
        maxHeapify(arr, 0, i);
    }
}

const arr = [4, 6, 3, 2, 9, 1];
heapSort(arr);

console.log("sorted array:", arr);

 

Implement pow(x, n)

[tabby title=”Task”]

Implement pow(x, n), which calculates x raised to the power n (i.e., xn).

 

Example 1:

Input:

 x = 2.00000, n = 10

Output:

 1024.00000

Example 2:

Input:

 x = 2.10000, n = 3

Output:

 9.26100

Example 3:

Input:

 x = 2.00000, n = -2

Output:

 0.25000

Explanation:

 2

-2

 = 1/2

2

 = 1/4 = 0.25

 

Constraints:

  • -100.0 < x < 100.0
  • -231 <= n <= 231-1
  • -104 <= xn <= 104

This problem was taken from https://leetcode.com/problems/powx-n/

 

[tabby title=”Solution”]

 

Brute force solution:

Straight forward, but we have to consider negative ranges.

/**
 * @param {number} x
 * @param {number} n
 * @return {number}
 */
var myPow = function(x, n) {
    
    if(n === 0) {
        return 1;
    }

    var N = n;
    var X = x;
    var result = 1;
    
    if(n < 0) {
        X = 1 / x;
        N = -n;
    }
    
    for(var i = 0; i < N; i ++) {
        result = result * X;
    }  
    return result;
};

 

Approach 2: Fast Power Algorithm Recursive

  • divide n so you immediately cut the computation time in half to logarithmic one.

pow of 2 to the power of 6

 

 

/**
 * @param {number} x
 * @param {number} n
 * @return {number}
 */
var myPow = function(x, n) {
    
    function fastPow(x, n) {
        if(n < 1) {
            return 1;
        }
        var half = fastPow(x, Math.floor(n / 2));

        if(n % 2 == 0) {
            return half * half;
        }
        else {
            return half * half * x;
        }
    }
    
    var X = x;
    var N = n;
    if(n < 0) {
        X = 1 / x;
        N = -n;        
    }
    return fastPow(X, N);
    
};

 

 

[tabbyending]