Showing posts with label time O(n^2). Show all posts
Showing posts with label time O(n^2). Show all posts

Saturday, September 27, 2014

Given an n x n square matrix, find sums of all sub-squares of size k x k

Problem:
Given an n x n square matrix, find sums of all sub-squares of size k x k where k is smaller than or equal to n.
Examples:

Input:
n = 5, k = 3
arr[][] = { {1, 1, 1, 1, 1},
            {2, 2, 2, 2, 2},
            {3, 3, 3, 3, 3},
            {4, 4, 4, 4, 4},
            {5, 5, 5, 5, 5},
         };
Output:
       18  18  18
       27  27  27
       36  36  36


Input:
n = 3, k = 2
arr[][] = { {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9},
         };
Output:
       12  16
       24  28


Solution:
Pre-process the matrix by calculating sums of all vertical strips of size 1 x k. Note that you can use the "rolling window" approach to calculate subsequent sums in the same column in O(1) time.
Then use the calculated sums and, again, the rolling window approach to calculate the k x k squares' sums.


Complexity:
time - O(n^2)
space - O(n)
Links and credits:
http://www.geeksforgeeks.org/given-n-x-n-square-matrix-find-sum-sub-squares-size-k-x-k/

Sunday, September 22, 2013

Print Postorder traversal from given Inorder and Preorder traversals

Problem:
Given Inorder and Preorder traversals of a binary tree, print Postorder traversal.

Example:
Input:
Inorder traversal in[] = {4, 2, 5, 1, 3, 6}
Preorder traversal pre[] = {1, 2, 4, 5, 3, 6}

Output:
Postorder traversal is {4, 5, 2, 6, 3, 1}

Trversals in the above example represents following tree

         1
      /     \   
     2       3
   /   \      \
  4     5      6

Solution:
A naive method is to first construct the tree, then use simple recursive method to print postorder traversal of the constructed tree. We can print postorder traversal without constructing the tree.
  1. The pre[0] is the root of the tree --> 1
  2. The in[] represents the tree as:

    { { left-sub-tree } ;  root ;   { right-sub-tree } }

    So the index of the root at in[] is the length of the left sub-tree --> 3
  3. The (in[].length - rootIndex - 1) is the length of the right sub-tree --> 2
  4. The pre[] represents the tree as:

    { root ;   { left-sub-tree } ;  { right-sub-tree } }

    Since we know the lengths of the sub-trees from steps #2 and #3, we can proceed recursively as follows:

    leftIn[] = in[ 0 .. (rootIndex-1) ] = { 4, 2, 5 }
    leftPre[] = pre[ 1 .. (rootIndex-2) ] = { 2, 4, 5 }

    rightIn[] = in[ (rootIndex+1) .. (length-1) ] = { 3, 6 }
    rightPre[] = pre[ (rootIndex+1) .. (length-1) ] = { 3, 6 }

    Recursion ends when the lengths of the in[] and pre[] become equal to 1.

int search(int arr[], int x, int n)
{
    for (int i = 0; i < n; i++)
      if (arr[i] == x)
         return i;
    return -1;
}
 
// Prints postorder traversal from given inorder and preorder traversals
void printPostOrder(int in[], int pre[], int n)
{
   // The first element in pre[] is always root, search it
   // in in[] to find left and right subtrees
   int root = search(in, pre[0], n);
 
   // If left subtree is not empty, print left subtree
   if (root != 0)
      printPostOrder(in, pre+1, root);
 
   // If right subtree is not empty, print right subtree
   if (root != n-1)
      printPostOrder(in+root+1, pre+root+1, n-root-1);
 
   // Print root
   cout << pre[0] << " ";
}


Complexity:
time - O(n^2)
space - O(n)
Links and credits:
http://www.geeksforgeeks.org/print-postorder-from-given-inorder-and-preorder-traversals/

Saturday, July 20, 2013

Construct a binary tree from inorder and preorder traversals

Problem:
Construct a BST from inorder and preorder traversal string

Solution:
Let us consider the below traversals:
Inorder sequence: D B E A F C
Preorder sequence: A B D E C F
In a Preorder sequence, leftmost element is the root of the tree. So we know ‘A’ is root for given sequences. By searching ‘A’ in Inorder sequence, we can find out all elements on left side of ‘A’ are in left subtree and elements on right are in right subtree. So we know below structure now.
                 A
               /   \
             /       \
           D B E     F C
We recursively follow above steps and get the following tree.
         A
       /   \
     /       \
    B         C
   / \        /
 /     \    /
D       E  F

struct node* buildTree(char in[], char pre[], int inStrt, int inEnd)
{
  static int preIndex = 0;
 
  if(inStrt > inEnd)
     return NULL;
 
  /* Pick current node from Preorder traversal using preIndex
    and increment preIndex */
  struct node *tNode = newNode(pre[preIndex++]);
 
  /* If this node has no children then return */
  if(inStrt == inEnd)
    return tNode;
 
  /* Else find the index of this node in Inorder traversal */
  int inIndex = search(in, inStrt, inEnd, tNode->data);
 
  /* Using index in Inorder traversal, construct left and
     right subtress */
  tNode->left = buildTree(in, pre, inStrt, inIndex-1);
  tNode->right = buildTree(in, pre, inIndex+1, inEnd);
 
  return tNode;
}


Complexity:
time - O(n^2)
space - O(n)
Links and credits:
http://www.careercup.com/question?id=21296665
http://www.geeksforgeeks.org/construct-tree-from-given-inorder-and-preorder-traversal/
http://discuss.leetcode.com/questions/148/construct-binary-tree-from-preorder-and-inorder-traversal

Sunday, July 14, 2013

Find all combinations summing up to a given target

Problem:
In a given array a = {1, 7, 3, 4, 5, 6, 2} Print the indices of all the combinations which lead to a given sum called target. For e.g. if the method is
Void PrintAllSumCombos(int[] arr, int target) - and the array shown above is passed with sum target = 7, then the output should be:

0, 3, 6
0, 5
1
2, 3
4, 6

Note: For simplicity, You may assume the array does not contain any negative numbers and also consider same set of indices with a different order as identical - for e.g. if 2, 3 is already printed, ignore 3, 2 as they are one and the same.

Solution:
A simple  and straightforward solution is to examine all possible combinations recursively, and print those that sum up to the target:

void PrintAllSumCombos(int arr[], int target,int start,int taken[],int count) {
   if (target==0) {
      for (int i =0;i<count;i++) {
         cout << taken[i] << " ";
      }
      cout << "\n";
      return ;
   }
   if (target ==-1 || start > 7) {
      return ;
   }
   for(int i=start; i < 7 ;i++) {
      taken[count]=i;
   }
}
int main() {
   int a[7]={1, 7, 3, 4, 5, 6, 2};
   int b[7];
   PrintAllSumCombos(a, 7,0,b,0) ;

   return 0;
}

However, there must exist a more efficient dynamic programming solution. Basic idea: examine each element of the array. Drop those that are greater than the target (because all the elements are non-negative). Also drop all elements equal to the target and print their indexes (tricky part if we should account for zeroes, but this is doable - just don't drop the elements that are equal to the target then). Now we're left with items that are less than the target. We must now produce all possible pairs, remembering the indexes of the pair elements, calculate their sum and perform the same procedure as for single elements (dropping/printing the pairs as necessary). So we end up with a list of pairs with sums less than the target. Continue this until the list is empty. The worst case time complexity of this algorithm is still O(n ^ 2), however, in average case it must be more efficient because we examine less and less elements on each step due to dropping those that are too large.

Complexity:
time - O(n ^ 2)
space - O(n)
Links and credits:
http://www.careercup.com/question?id=21383667

Wednesday, June 26, 2013

Given a string find the largest substring which is palindrome

Problem:
Given a string find the largest substring which is palindrome.

Solution:
Test if a substring is a palindrome starting from its potential "center":

int longestPalindromicSubstring(char* str)
{
 int len = strlen(str);
 int maxLength = 1;
 int start = 0;
 int low, high;
 
 for(int i = 1; i < len; i++)
 {
  // Find longest even length palindrome with
  // center points as i-1 and i
  low = i-1;
  high = i;
  while(low >= 0 && high < len && str[low] == str[high])
  {
   if(high - low + 1 > maxLength)
   {
    start = low;
    maxLength = high - low + 1;
   }
   low--;
   high++;
  }
  
  // Find longest odd length palindrom with
  // center point as i
  low = i-1;
  high = i+1;
  while(low >= 0 && high < len && str[low] == str[high])
  {
   if(high - low + 1 > maxLength)
   {
    start = low;
    maxLength = high - low + 1;
   }
   low--;
   high++;
  }
 }
 
 printf("Longest Palindromic Substring is: ");
 for(int i = start; i <= start + maxLength - 1; i++)
 {
  printf("%c", str[i]);
 }
 
 return maxLength;
}


Complexity:
time - O(n^2)
space - O(1)
Links and credits:
http://www.careercup.com/question?id=20351666
O(n) algorithm (Manacher's Algorithm) is discussed at http://discuss.leetcode.com/questions/178/longest-palindromic-substring