Algorithm Misc 2


http://www.geeksforgeeks.org/subarraysubstring-vs-subsequence-and-programs-to-generate-them/
How to generate all subarrays?
We can run two nested loops, the outer loop picks starting element and inner loop considers all elements on right of the picked elements as ending element of subarray.
void subArray(int arr[], int n)
{
    // Pick starting point
    for (int i=0; i <n; i++)
    {
        // Pick ending point
        for (int j=i; j<n; j++)
        {
            // Print subarray between current starting
            // and ending points
            for (int k=i; k<=j; k++)
                cout << arr[k] << " ";
            cout << endl;
        }
    }
}

http://www.geeksforgeeks.org/maximum-difference-between-frequency-of-two-elements-such-that-element-having-greater-frequency-is-also-greater/
Given an array of n positive integers with many repeating elements. The task is to find maximum difference between the frequency of any two different elements, such that the element with greater frequency is also greater in value than the second integer.
The naive approach can be, find the frequency of each element and for each element find the element having lesser value and lesser frequency than the current element.
int maxdiff(int arr[], int n)
{
    unordered_map<int, int> freq;
    // Finding the frequency of each element.
    for (int i = 0; i < n; i++)
        freq[arr[i]]++;
    int ans = 0;
    for (int i=0; i<n; i++)
    {
        for (int j=0; j<n; j++)
        {
            // finding difference such that element
            // having greater frequency is also
            // greater in value.
            if (freq[arr[i]] > freq[arr[j]] &&
                arr[i] > arr[j] )
                ans = max(ans, freq[arr[i]]-freq[arr[j]]);
            else if (freq[arr[i]] < freq[arr[j]] &&
                      arr[i] < arr[j] )
                ans = max(ans, freq[arr[j]]-freq[arr[i]]);
        }
    }
    return ans;
}
Method 2 (Use Hashing and Sorting):

The idea is to find all the distinct elements and store in an array, say dist[ ]. Sort the distinct element array dist[] in increasing order. Now for any distinct element at index i, for all index j such that i > j > 0, find the element between index 0 to i-1 having minimum frequency. We can find frequency of an element in same way as method 1, i.e., storing frequencies in a hash table.
So do this for all i and find the maximum difference. To find the minimum frequency for all i maintain a prefix minimum.
int maxdiff(int arr[], int n)
{
    unordered_map<int, int> freq;
    int dist[n];
    // Finding the frequency of each element.
    int j = 0;
    for (int i = 0; i < n; i++)
    {
        if (freq.find(arr[i]) == freq.end())
            dist[j++] = arr[i];
        freq[arr[i]]++;
    }
    // Sorting the distinct element
    sort(dist, dist + j);
    int min_freq = n+1;
    // Iterate through all sorted distinct elements.
    // For each distinct element, maintaining the
    // element with minimum frequency than that
    // element and also finding the maximum
    // frequency difference
    int ans = 0;
    for (int i=0; i<j; i++)
    {
        int cur_freq = freq[dist[i]];
        ans = max(ans, cur_freq - min_freq);
        min_freq = min(min_freq, cur_freq);
    }
    return ans;
}
http://www.geeksforgeeks.org/find-if-n-can-be-written-as-product-of-k-numbers/
Given a positive number n, we need to print exactly k positive numbers (all greater than 1) such that product of those k numbers is n. If there doesn’t exist such k numbers, print -1 . If there are many possible answer you have to print one of that answer where k numbers are sorted.
void kFactors(int n, int k)
{
    // A vector to store all prime factors of n
    vector<int> P;
    // Insert all 2's in vector
    while (n%2 == 0)
    {
        P.push_back(2);
        n /= 2;
    }
    // n must be odd at this point
    // So we skip one element (i = i + 2)
    for (int i=3; i*i<=n; i=i+2)
    {
        while (n%i == 0)
        {
            n = n/i;
            P.push_back(i);
        }
    }
    // This is to handle when n > 2 and
    // n is prime
    if (n > 2)
        P.push_back(n);
    // If size(P) < k, k factors are not possible
    if (P.size() < k)
    {
        cout << "-1" << endl;
        return;
    }
    // printing first k-1 factors
    for (int i=0; i<k-1; i++)
        cout << P[i] << ", ";
    // calculating and printing product of rest
    // of numbers
    int product = 1;
    for (int i=k-1; i<P.size(); i++)
        product = product*P[i];
    cout << product << endl;
}

http://www.geeksforgeeks.org/sort-array-converting-elements-squares/
Given a array of both positive and negative integers ‘arr[]’ which are sorted. Task is to sort square of the numbers of the Array.
  1. Divide the array into two part “Negative and positive “.
  2. Use merge function to merge two sorted arrays into a single sorted array.
    public static void sortSquares(int arr[])
    {
        int n = arr.length;
       // first dived array into part negative and positive
       int k;
       for(k = 0; k < n; k++)
       {
           if(arr[k] >= 0)
             break;
       }
         
        // Now do the same process that we learn
        // in merge sort to merge to two sorted array
        // here both two half are sorted and we traverse
        // first half in reverse meaner because
        // first half contain negative element
        int i = k-1; // Initial index of first half
        int j = k; // Initial index of second half
        int ind = 0; // Initial index of temp array
         
        int[] temp = new int[n];
        while(i >= 0 && j < n)
        {
            if(arr[i] * arr[i] < arr[j] * arr[j])
            {
                temp[ind] = arr[i] * arr[i];
                i--;
            }
            else{
                 
                temp[ind] = arr[j] * arr[j];
                j++;
                 
            }
            ind++;
        }
         
        while(i >= 0)
        {
            temp[ind++] = arr[i] * arr[i];
            i--;
        }
        while(j < n)
        {
            temp[ind++] = arr[j] * arr[j];
            j++;
        }
         
       // copy 'temp' array into original array
        for (int x = 0 ; x < n; x++)
            arr[x] = temp[x];
    }

Simple solution is to first convert each array elements into its square and than apply any “O(nlogn)” sorting algorithm to sort the array elements.
http://www.geeksforgeeks.org/a-permutation-where-each-element-indicates-either-number-of-elements-before-or-after-it/
Given an array of n elements. The task is to check whether a permutation of given array exists, such that each element indicate number of element present before or after it. Print “Yes” if exists, else print “No”.
The idea is to use hashing. Observe, for each index i in the array, arr[i] can have value i or n – i. We traverse the given array and find the frequency of each element present in the array. Now, for each index i, check availability of value i and n-i and accordingly decrement the frequency. Note that an item with value i can either go to index i or n-i-1. Similarly, an item with value n-i-1 can go to either index i or n-i-1.
   {
        int n = arr.length;
        int[] freq = new int[n];
  
        // Finding the frequency of each number.
        for (int i = 0; i < n; i++)
            freq[arr[i]]++;
  
        for (int i = 0; i < n; i++)
        {
            // Try to find number of element before
            // the current index.
            if (freq[i]!= 0)
                 freq[i]--;
  
            // Try to find number of element after
            // the current index.
            else if (freq[n-i-1]!= 0)
                    freq[n-i-1]--;
  
            // If no such number find, return false.
            else
                return false;
        }
  
    return true;
    }

http://www.geeksforgeeks.org/sum-dependencies-graph/
Given a directed and connected graph with n nodes. If there is an edge from u to v then u depends on v. Our task was to find out the sum of dependencies for every node.
Idea is to check adjacency list and find how many edges are there from each vertex and return the total number of edges.
void addEdge(vector <int> adj[], int u,int v)
{
    adj[u].push_back(v);
}
// find the sum of all dependencies
int findSum(vector<int> adj[], int V)
{
    int sum = 0;
    // just find the size at each vector's index
    for (int u = 0; u < V; u++)
        sum += adj[u].size();
    return sum;
}
http://www.geeksforgeeks.org/seeds-of-a-number/
A Seed of a number n is a number x such that multiplication of x with its digits is equal to n. The task is to find all seeds of a given number n. If no seed exists, then print the same.
The idea is to traverse all numbers from 1 to n/2. For every number being traversed, find product of digits with the number. An important optimization done in below program is to avoid re-computations of digit products. We store the products in an array. If a product has already been computed, we return it, else we compute it.
We can further optimize above code. The idea is to make a call to getDigitProduct(i) only if i is divisible by n

const int MAX = 10000;
int prodDig[MAX];
// Stores product of digits of x in prodDig[x]
int getDigitProduct(int x)
{
    // If x has single digit
    if (x < 10)
      return x;
    // If digit product is already computed
    if (prodDig[x] != 0)
       return prodDig[x];
    // If digit product is not computed before.
    int prod = (x % 10) * getDigitProduct(x/10);
    return (prodDig[x] = prod);
}
// Prints all seeds of n
void findSeed(int n)
{
    // Find all seeds using prodDig[]
    vector<int> res;
    for (int i=1; i<=n/2; i++)
        if (i*getDigitProduct(i) == n)
            res.push_back(i);
    // If there was no seed
    if (res.size() == 0)
    {
        cout << "NO seed exists\n";
        return;
    }
    // Print seeds
    for (int i=0; i<res.size(); i++)
        cout << res[i] << " ";
}
Maximize sum of consecutive differences in a circular array
Given an array of n elements. Consider array as circular array i.e element after an is a1. The task is to find maximum sum of the difference between consecutive elements with rearrangement of array element allowed i.e after rearrangement of element find |a1 – a2| + |a2 – a3| + …… + |an – 1 – an| + |an – a1|.
The idea is to use Greedy Approach and try to bring elements having greater difference closer.
Consider the sorted permutation of the given array a1, a1, a2,…., an – 1, an such that a1 < a2 < a3…. < an – 1 < an.
Now, to obtain the answer having maximum sum of difference between consecutive element, arrange element in following manner:
a1, an, a2, an-1,…., an/2, a(n/2) + 1
We can observe that the arrangement produces the optimal answer, as all a1, a2, a3,….., a(n/2)-1, an/2 are subtracted twice while a(n/2)+1, a(n/2)+2, a(n/2)+3,….., an – 1, an are added twice.
int maxSum(int arr[], int n)
{
    int sum = 0;
    // Sorting the array.
    sort(arr, arr + n);
    // Subtracting a1, a2, a3,....., a(n/2)-1, an/2
    // twice and adding a(n/2)+1, a(n/2)+2, a(n/2)+3,.
    // ...., an - 1, an twice.
    for (int i = 0; i < n/2; i++)
    {
        sum -= (2 * arr[i]);
        sum += (2 * arr[n - i - 1]);
    }
    return sum;
}

http://www.geeksforgeeks.org/count-all-pairs-of-an-array-which-differ-in-k-bits/
Given an array of size n and integer k, count all pairs in array which differ in exactly K bits of binary representation of both the numbers.
This approach is efficient for the cases when input array has small elements and possibly many repetitions. The idea is to iterate from 0 to max(arr[i]) and for every pair(i, j) check the number of set bits in (i ^ j) and compare this with K. We can use inbuilt function of gcc( __builtin_popcount ) or precompute such array to make the check faster. If number of ones in i ^ j is equals to K then we will add the total count of both i and j.
long long kBitDifferencePairs(int arr[], int n, int k)
{
    // Get the maximum value among all array elemensts
    int MAX = *max_element(arr, arr+n);
    // Set the count array to 0, count[] stores the
    // total frequency of array elements
    long long count[MAX+1];
    memset(count, 0, sizeof(count));
    for (int i=0; i < n; ++i)
        ++count[arr[i]];
    // Initialize result
    long long ans = 0;
    // For 0 bit answer will be total count of same number
    if (k == 0)
    {
        for (int i = 0; i <= MAX; ++i)
            ans += (count[i] * (count[i] - 1)) / 2;
        return ans;
    }
    for (int i = 0; i <= MAX; ++i)
    {
        // if count[i] is 0, skip the next loop as it
        // will not contribute the answer
        if (!count[i])
           continue;
        for (int j = i + 1; j <= MAX; ++j)
        {
            //Update answer if k differ bit found
            if ( __builtin_popcount(i ^ j) == k)
                ans += count[i] * count[j];
        }
    }
    return ans;
}
int bitCount(int n)
{
    int count = 0;
    while (n)
    {
        if (n & 1)
            ++count;
        n >>= 1;
    }
    return count;
}
// Function to count pairs of K different bits
long long countPairsWithKDiff(int arr[], int n, int k)
{
    long long ans = 0; // initialize final answer
    for (int i = 0; i < n-1; ++i)
    {
        for (int j = i + 1; j < n; ++j)
        {
            int xoredNum = arr[i] ^ arr[j];
            // Check for K differ bit
            if (k == bitCount(xoredNum))
                ++ans;
        }
    }
    return ans;
}

面试题应该来源实践
我觉得面试题应该来源于实践的,而这类题目却与实践大大脱节,它考察的是一个人有没有刻意去准备。我可以立刻想到一些实用的面试题,都是实践中遇到的:
1.在一块矩形区域内随机选取一些点,要求任意两个点之间的距离不小于一个值
这个是一个同事做的一款手机游戏中的一关,它要在屏幕上随机位置生成一些鬼火,然后用多个手指 点同时把所有的鬼火都点上,就可以过关了。大概随机出5到6个点就够了,如果点数更多可以加大难度。因为位置随机,如果两个点靠得太近,手指的姿势会很别扭,会很不好点。
回到题目,菜鸟级别应该立马可以想到最暴力的方法,随便生成一些点,然后做校验,如果满足条件就退出,否则再随机生成一批数据。分析一下复杂度,生成数据O(n),校验数据O(n^2)。如果能想着排序之类的方式去把校验过程的复杂度优化,就是不错的引导。面试应该这种开放式的讨论,不是考察面试者准备的怎么样。
由于校验后不一定满足,可能很多计算都是浪费的。所以,杀一点脑细胞的方式就会再继续思考。在构造的时候就生成满足条件的点。
比如我们可以对矩形区域打一些格子,然后用一个二维数组来标记这些格子。格子的直径的两倍大于要求的距离。然后我们来随机选格子而不是选点。选完一个格子以后,就将它周围格子标记起来,下一次随机选格子的时候,不能选择被标记的格子。最后从选择的格子中去取点,每个格子取一个,由于格子间距离是能保证大于一定值的,最终选取的任意两个点间的距离也是不小于一个值的。
当然,这不是最优解。我可以告诉你工程中最简单的做法,我同事的做法:自已用手在屏幕上点了一些点(感觉大概两个之间距离差不多就行),记录下坐标,存到数组里。然后使用的时候随便到从中取一些就行了......这才是高大上,丝毫不装逼。
2.有很多大小不一的小矩形,如何将它们填充到一个大矩形里面,使得填充得尽量的满,空间利用率尽量高。
做过游戏的人应该都知道texture packer,就是合图啦。把许许多多的小图合到一张大图里,抽象出来就是上面这个问题。
任选一个小矩形,放进去,大矩形剩下的区域就可以分为两个矩形,有两种分法。然后对子矩形递归地执行这个划分过程,就可以得到所有可能的方法。这是暴力的做法。
但是这状态数增长得太夸张,然后就应该思考有什么规律能利用到,比如按从大到小先将小矩形排序。
其实,有更好的答案:问google。这才是最工程的做法,绝对比自己闷着头想来得容易。


Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts