LeetCode 954 - Array of Doubled Pairs


https://leetcode.com/problems/array-of-doubled-pairs/
Given an array of integers A with even length, return true if and only if it is possible to reorder it such that A[2 * i + 1] = 2 * A[2 * i] for every 0 <= i < len(A) / 2.

    Example 1:
    Input: [3,1,3,6]
    Output: false
    
    Example 2:
    Input: [2,1,2,6]
    Output: false
    
    Example 3:
    Input: [4,-2,2,-4]
    Output: true
    Explanation: We can take two groups, [-2,-4] and [2,4] to form [-2,-4,2,4] or [2,4,-2,-4].
    
    Example 4:
    Input: [1,2,4,16,8,4]
    Output: false
    

    Note:
    1. 0 <= A.length <= 30000
    2. A.length is even
    3. -100000 <= A[i] <= 100000

    https://blog.csdn.net/fuxuemingzhu/article/details/84925747
    题目的意思是奇数位置的数字能不能安排成它左边的那个位置的二倍。

    使用的方法是统计次数、然后遍历查找的方式,和Two Sum之类的很类似。需要注意的是,我们对数组进行了排序,这样保证下面的遍历是从小到大开始的。另外,由于排序之后,对于负数而言,小数字是大数字的2倍,所以,需要做一个正负的判断。

    对于负数来说,我们找出它的1/2是不是在数组中;对于正数来说,我们找出它的2倍是不是在数组中。如果找到了要找的数字之后,把它的次数减去当前的数字的次数,以方便后面的统计。所以,如果所有的数字都满足条件的话,那么就一波一波的都消除掉了。



    https://leetcode.com/articles/array-of-doubled-pairs/
    If x is currently the array element with the least absolute value, it must pair with 2*x, as there does not exist any other x/2 to pair with it.
    Algorithm
    Let's try to (virtually) "write" the final reordered array.
    Let's check elements in order of absolute value. When we check an element x and it isn't used, it must pair with 2*x. We will attempt to write x, 2x - if we can't, then the answer is false. If we write everything, the answer is true.
    To keep track of what we have not yet written, we will store it in a count.

      public boolean canReorderDoubled(int[] A) {
        // count[x] = the number of occurrences of x in A
        Map<Integer, Integer> count = new HashMap();
        for (int x : A)
          count.put(x, count.getOrDefault(x, 0) + 1);

        // B = A as Integer[], sorted by absolute value
        Integer[] B = new Integer[A.length];
        for (int i = 0; i < A.length; ++i)
          B[i] = A[i];
        Arrays.sort(B, Comparator.comparingInt(Math::abs));//\\

        for (int x : B) {
          // If this can't be consumed, skip
          if (count.get(x) == 0)
            continue;
          // If this doesn't have a doubled partner, the answer is false
          if (count.getOrDefault(2 * x, 0) <= 0)
            return false;

          // Write x, 2*x
          count.put(x, count.get(x) - 1);
          count.put(2 * x, count.get(2 * x) - 1);
        }

        // If we have written everything, the answer is true
        return true;

      }

    https://leetcode.com/problems/array-of-doubled-pairs/discuss/203183/JavaC%2B%2BPython-Match-from-the-Smallest-or-Biggest-100
    Assume all interger are positive, for example [2,4,4,8].
    We have one x = 2, we need to match it with one 2x = 4.
    Then one 4 is gone, we have the other x = 4.
    We need to match it with one 2x = 8.
    Finaly no number left.
    Why we start from 2?
    Because it's the smallest and we no there is no x/2 left.
    So we know we need to find 2x
    What if the case negative?
    One way is that start from the biggest (with abosolute value smallest),
    and we aplly same logic.
    Another way is that start from the smallest (with abosolute value biggest),
    and we try to find x/2 each turn.

    Explanation

    1. Count all numbers.
    2. Loop all numbers on the order of its absolute.
      We have counter[x] of x, so we need the same amount of 2x wo match them.
      If c[x] > c[2 * x], then we return false
      If c[x] <= c[2 * x], then we do c[2 * x] -= c[x] to remove matched 2x.
    Don't worry about 0, it doesn't fit the logic above but it won't break our algorithme.
    In case count[0] is odd, it won't get matched in the end.
    (Anyway you can return false earlier here)
    In case count[0] is even, we still have c[0] <= c[2 * 0].
    And we still need to check all other numbers.


        public boolean canReorderDoubled(int[] A) {
            Map<Integer, Integer> count = new TreeMap<>();
            for (int a : A)
                count.put(a, count.getOrDefault(a, 0) + 1);
            for (int x : count.keySet()) {
                if (count.get(x) == 0) continue;
                int want = x < 0 ? x / 2 : x * 2;
                if (x < 0 && x % 2 != 0 || count.get(x) > count.getOrDefault(want, 0))
                    return false;
                count.put(want, count.get(want) - count.get(x));
            }
            return true;
        }
    
    http://morecoder.com/article/1136796.html
    If the input array is not sorted, then it is difficult to know for A[2 * i], whether it should be used to match A[2 * i + 1] = 2 * A[2 * i] or A[2 * i] = 2 * A[2 * i - 1]. But if we sort the input array, it makes this matching process easier as shown in the following.
    For all the sorted negative integers, start to match from smallest to largest; (-4 < -2)
    For all the sorted positive integers, start to match from smallest to largest; (2 < 4)

    When following the above match order, we know that in order to be able to make this array a complete doubled pairs, if there are m of integer a, then there must be at least m of integer 2 * a(for a >= 0) or a /2 (for a < 0).
    As a result, we need a fast way to keep all the counts of unused integers, a hint for hash map. The keys would be all the integers and the values are the frequencies of these integers. Combined with the need of having all integers in sorted order, we use TreeMap.


    The runtime is O(N * logN), constructing the tree map is the dominant part of the runtime.
    X. https://www.acwing.com/solution/leetcode/content/686/
    https://zhanghuimeng.github.io/post/leetcode-954-array-of-doubled-pairs/
    这道题用贪心就可以解决。对于当前还剩的绝对值最小的数,它必然需要和它的两倍的数配对;最后所有的数都需要配对完。以及0只能自己和自己配对,所以0的总数应该是偶数。
        bool canReorderDoubled(vector<int>& A) {
            int positive[100001], negative[100001];
            memset(positive, 0, sizeof(positive));
            memset(negative, 0, sizeof(negative));
            for (int x: A) {
                if (x >= 0) positive[x]++;
                else negative[-x]++;
            }
            if (positive[0] % 2 != 0) return false;
            for (int i = 1; i <= 100000; i++) {
                if (positive[i] != 0) {
                    if (i > 50000 || positive[i*2] < positive[i]) return false;
                    positive[i*2] -= positive[i];
                }
            }
            for (int i = 1; i <= 100000; i++) {
                if (negative[i] != 0) {
                    if (i > 50000 || negative[i*2] < negative[i]) return false;
                    negative[i*2] -= negative[i];
                }
            }
            return true;
        }

    https://leetcode.com/problems/array-of-doubled-pairs/discuss/203308/Java-Solution-one-hashmap-only-(for-both-positive-and-negative-numbers)-!
    // (0). one map only: to count the frequency of apperance of each number
    // (1). Sort the array, then scan from the smalllest to find (x, 2x) pairs
    // ___ (a) for negative number, we will see 2x first, the match should be half of it.
    // ___ (b). for positive, we will see x first, the match should be two times of it.
    // (2) once matched, update the map
    // (3). no need to put 0 into the map.
    Example: [3, 6, -4, -2, 0, 0, 14, 7, -2, -4]
    Your stdout
    map: {-2=2, -4=2, 3=1, 6=1, 7=1, 14=1}
    map: {-2=0, -4=0, 3=1, 6=1, 7=1, 14=1} after process (-4, -2) pair
    map: {-2=0, -4=0, 3=0, 6=0, 7=1, 14=1} after process (3, 6) pair
    map: {-2=0, -4=0, 3=0, 6=0, 7=0, 14=0} after process (7, 14) pair
    public boolean canReorderDoubled(int[] A) {
        
        int n = A.length;
        if (n % 2 != 0) return false;
        Arrays.sort(A);
        Map<Integer, Integer> map = new HashMap<>(); // <num, freq>
        for (int item : A) {
            if (item == 0) continue;
            map.put(item, map.getOrDefault(item, 0) + 1);
        }
        for (int i = 0; i < n; i++) {
            if (A[i] != 0 && map.get(A[i]) > 0) {
                //System.out.println("map: " + map);
                int target = A[i] * 2; // (3). positive, target = 2x 
                if (A[i] < 0) { // (2) for negative (-4), the match should be half of it. 
                    if (A[i] % 2 != 0) { // A[i] = -7, A[i] / 2 = -3
                        return false;
                    } else {
                        target = A[i] / 2; // negative: target = x
                    }
                }
                if (map.getOrDefault(target, 0) < map.get(A[i])) {
                    return false;
                } else {
                    // (4) once matched, update the map
                    map.put(target, map.get(target)  - map.get(A[i]));
                    map.put(A[i], 0);
                }
            }
        }
        //System.out.println("map: " + map);
        return true;
    
        
    }
    
    https://leetcode.com/problems/array-of-doubled-pairs/discuss/203348/Easy-Understand-JAVA-Solution
    https://leetcode.com/problems/array-of-doubled-pairs/discuss/203191/JAVA-17ms-O(200000)-without-Sorting-but-with-Explanation
    map.put(item, map.getOrDefault(item, 0) + 1); you could simply write map.merge(item, 1, Integer::sum);?

    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