Codility - MinAbsSum (Min Abs Sum)


Codility and other programming lessons: Lesson 15: MinAbsSum (Min Abs Sum)
For a given array A of N integers and a sequence S of N integers from the set {−1, 1}, we define val(A, S) as follows:
val(A, S) = |sum{ A[i]*S[i] for i = 0..N−1 }|
(Assume that the sum of zero elements equals zero.)
For a given array A, we are looking for such a sequence S that minimizes val(A,S).
Write a function:
int solution(int A[], int N);
that, given an array A of N integers, computes the minimum value of val(A,S) from all possible values of val(A,S) for all possible sequences S of N integers from the set {−1, 1}.
For example, given array:
  A[0] =  1
  A[1] =  5
  A[2] =  2
  A[3] = -2
your function should return 0, since for S = [−1, 1, −1, 1], val(A, S) = 0, which is the minimum possible value.
Assume that:
  • N is an integer within the range [0..20,000];
  • each element of array A is an integer within the range [−100..100].
Complexity:
  • expected worst-case time complexity is O(N*max(abs(A))2);
  • expected worst-case space complexity is O(N+sum(abs(A))), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
https://codility.com/media/train/solution-min-abs-sum.pdf
Since we can arbitrarily choose to take the element or its negative, we can simplify the problem and replace each number with its absolute value. Then the problem becomes dividing the numbers into two groups and making the di erence between the sums of the two groups as small as possible. It is a classic dynamic programming problem.

Assume the sum of absolute values of all the numbers is S. We want to choose some of the numbers (absolute values) to make their sum as large as possible without exceeding S2 . Why? Let P be the sum of the first group, Q be the sum of the other group and P < Q. We have P ¬ S2 ¬ Q and Q + P = S. The larger is P , the smaller is Q and the di erence QP . Hence, the largest possible P ¬ S2 gives the optimal result. Let M be the maximal element in the given array A. We create an array dp of size S.


Slow solution O(N2 · M)
1   def slow_min_abs_sum(A):

2                N = len(A)

3                M = 0

4          for i in xrange(N):

5                 A[i] = abs(A[i])

6                 M = max(A[i], M)

7                S = sum(A)
8          dp = [0] * (S + 1)
9                dp[0] = 1

10                for j in xrange(N):

11                          for i in xrange(S, -1, -1):

12                                     if (dp[i] == 1) and (i + A[j] <= S):

13                               dp[i + A[j]] = 1

14                result = S

15                for i in xrange(S // 2 + 1):


16                          if dp[i] == 1:
 17                 result = min(result, S - 2 * i)
18    return result

Golden solution O(N · M2)
1   def golden_min_abs_sum(A):

2                N = len(A)

3                M = 0

4          for i in xrange(N):

5                 A[i] = abs(A[i])

6                 M = max(A[i], M)

7                S = sum(A)
8          count = [0] * (M + 1)
9          for i in xrange(N):

10                          count[A[i]] += 1
11                dp = [-1] * (S + 1)
12                dp[0] = 0

13                for a in xrange(1, M + 1):

14                          if count[a] > 0:

15                                     for j in xrange(S):

16
if dp[j] >=
0:

17
dp[j] =
count[a]

18
elif (j >= a and dp[j
- a] > 0):
19
dp[j] =
dp[j - a]
- 1

20                result = S

21                for i in xrange(S // 2 + 1):

22                          if dp[i] >= 0:
23                                     result = min(result, S - 2 * i)
24                return result

The time complexity of the above solution is O(N · M 2), where M is the maximal element, since S = O(N · M) and there are at most M di erent values in A.
http://codesays.com/2014/solution-to-delta2011-min-abs-sum-by-codility/
def solution(A):
    # Since S could be 1 or -1, it does not matter that
    # each element in A is positive or negative.
    A = [abs(item) for item in A]
    sumOfA = sum(A)
    
    # Get the number distribution. So we do not need to try
    # each number for multiple times.
    numbers = {}
    for item in A:  numbers[item] = numbers.get(item, 0) + 1
 
    # This is the KEY point.
    # Typically, we will use possible = [False] * len to track, which numbers
    # could be the result by summing up subsets of A.
    # For a number, appeared for many times, there will be multiple attempts
    # for it. But in this way, when we are trying number n,
    # possible[i] == -1 means it is impossible.
    # possible[i] == i >= 0 means it is possible and there are i n(s) left to use.
    # So for ALL number n(s), we only need ONE scan over the record.
    possible = [-1] * (sumOfA // 2 + 1)
    possible[0] = 0
    
    for number in numbers:      # Try each distinct number
        for trying in xrange(sumOfA//2+1):
            if possible[trying] >= 0:
                # Can be reached with previous numbers
                possible[trying] = numbers[number]
            elif trying >= number and possible[trying-number] > 0:
                # Cannot be reached with only previous numbers.
                # But could be achieved with previous numbers AND current one.
                possible[trying] = possible[trying-number] - 1
    
    # Divide the A into two parts: P and Q, with restriction P <= Q.
    # So P <= sumOfA // 2 <= Q. We want the largest possible P, so that
    # Q-P is minimized.
    for halfSum in xrange(sumOfA//2, -1, -1):
        if possible[halfSum] >= 0:
            return sumOfA - halfSum - halfSum
    
    raise Exception("Should never be here!")
    return 0
Also check http://codesays.com/2014/solution-to-delta2011-min-abs-sum-by-codility/
(1) The O(N^2 * max(abs(A))) solution
Let dpi equal 1 if it is possible to achieve the sum of i using elements of A, and 0 otherwise
int solution(int A[], int N) 
{
    int max = 0;
    int sum = 0;
    
    for (int i = 0; i < N; i++){
        A[i] = abs(A[i]);
        max = max < A[i] ? A[i] : max;
        sum += A[i];
    }

    int memsize = sizeof(int) * (sum + 1);
    int* dp = (int*)alloca(memsize);
    memset(dp, 0x00, memsize);
    
    dp[0] = 1;
    for (int i = 0; i < N; i++){
        for (int j = sum; j >= 0; j--){
            if (dp[j] == 1 && j + A[i] <= sum){
                dp[j + A[i]] = 1;    
            }
        }
    }
    
    int result = sum;
    for (int p = 0; p * 2 <= sum; p++){
        if (dp[p] == 1){
            int q = sum - p;
            int diff = q - p;
            result = diff < result ? diff : result; 
        }
    }
    return result;
}
Golden solution O(N · M2)
• dpj = −1 if we cannot get the sum j, • dpj ­ 0 if we can get sum j.
int solution(int A[], int N) { int max = 0; int sum = 0; for (int i = 0; i < N; i++){ A[i] = abs(A[i]); max = max < A[i] ? A[i] : max; sum += A[i]; } //the absolute values of A[] are between [0..100] int num_memsize = sizeof(int) * (max + 1); int* count = (int*)alloca(num_memsize); memset(count, 0x00, num_memsize); for (int i = 0; i < N; i++){ count[A[i]]++; } int dp_memsize = sizeof(int) * (sum + 1); int* dp = (int*)alloca(dp_memsize); //clear up with -1. memset(dp, 0xFF, dp_memsize); dp[0] = 0; for (int i = 1; i <= max; i++){ if (count[i] <= 0){ continue; } for (int j = 0; j <= sum; j++){ if (dp[j] >= 0){ dp[j] = count[i]; } else if (j >= i && dp[j - i] > 0){ dp[j] = dp[j - i] - 1; } } } int result = sum; for (int p = 0; p * 2 <= sum; p++){ if (dp[p] >= 0){ int q = sum - p; int diff = q - p; result = diff < result ? diff : result; } } return result; }
http://phiphy618.blogspot.jp/2013/05/codility-delta-2011-minabssum.html
首先对数组做处理,负数转换成对应正数,零去掉,计数排序统计有多少个不同元素及其对应个数,并累加所有数的和sum,不妨记b=sum/2,不同元素个数为m,则目标转换为在m个不同元素中挑出若干个元素(每个元素可以重复多次,但少于它们的出现次数),使得它们的和不大于b并尽量接近。到了这里,应该有点熟悉的感觉了吧。对了,其实这就是0-1背包问题!

记 f[i][j] 为只允许选前 i 个元素,总和不超过 j ,则有 f[i][j] = max { f[i-1][j], f[i][j-D[i]]+D[i] }, 其中 D[i] 为第 i 个元素对应的值。由于每种元素的数量不是无穷多,因此对每个 f[i][j] ,都需要记录第 i 种元素的消耗数量,保证小于该元素的出现次数。
第一次的代码并未完全通过,75分,大数据全挂。原因是这里一个元素可以出现多次,是多重背包问题。
    public int solution(int[] A) {
        // write your code here...
        if (A.length == 0return 0;
         
        int sum = 0;
        int max = 0;
        for (int i = 0; i < A.length; i++) {
            if (A[i] < 0) A[i] = -A[i];
            sum += A[i];
        }
        int target = sum / 2;
        int dp[][] = new int[A.length][target];
        for (int i = 0; i < A.length; i++) {
            for (int j = 0; j < target; j++) {
                // j+1 is the weight limit
                if (i == 0)
                {
                    if (A[i] <= (j+1)) {
                        dp[i][j] = A[i];
                    }
                    else
                    {
                        dp[i][j] = 0;
                    }
                }
                else // i != 0
                {
                    int w1 = dp[i-1][j];
                    int w2 = 0;
                    if (j-A[i] >=0 ) {
                        w2 = dp[i][j-A[i]] + A[i];
                    }
                    dp[i][j] = w1 > w2 ? w1 : w2;
                }
            }
        }
        max = dp[A.length - 1][target - 1];
        return (sum - max * 2);
    }
to-do: http://codesays.com/2014/solution-to-min-abs-sum-of-two-by-codility/
Read full article from Codility and other programming lessons: Lesson 15: MinAbsSum (Min Abs 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