A Dynamic Planning question and Dynamic Planning
Description: Create a class called Football. in football, scores are incremented by eitsp2, 3, or 7 points. given a numerical input (integer between 1 and 75) representing a final score, calculate the number of all possible combinationsof (2, 3, 7) which add up to that score. the output shocould be the number ofcombinations found. here are a couple of examples:
Input | output | combinations1 04 1 (2, 2) 9 3 (2, 7), (2, 2, 2, 3), (3, 3, 3) 11 3 (2, 2, 7), (2, 2, 2, 2, 3), (2, 3, 3)
Here is the method signature (be sure your method is public: int fetchCombinations (int input)
We will check to make sure the input to this problem is valid.
It is actually an input number and an array to calculate the number of different combinations so that only the number in the array (which can be repeated) is used to add the result equal to the input number.
Assume that the number of inputs is 11 and the array is [2, 3, 7]. Output 3 indicates three different combinations: (2, 2, 7), (2, 7, 2, 2, 2, 3), (2, 3, 3)
I have two solutions: 1. the first method is the brute-force recursion method. Assume that the input number is N, and the array is [a, B, c, d]. the definition of calling a recursive function is recursion (int num, List <Integer> result). The input list is empty during initialization, when num is equal to 0, the result is added to the result set. If num is smaller than 0, the result is not a combination and is directly returned. Otherwise, the current array content is copied, then, add the array element k to the newly created array in sequence, and call the recursive recursion (num-k, new_result) function ); in this way, all the result sets can be obtained after recursion. 2. Use a method similar to dynamic planning: to calculate all possible combinations of N, it is equivalent to Calculating N-a, N-B, N-c, n-d combination, and then add a, B, c, or d to these combinations respectively. However, there may be some duplicates when calculating the child set, therefore, you can use a map to save the calculation results. Then, you can view the map before calculation. The key of this map is an integer, and value is a two-dimensional array. each item is a combination of results. Through the above method, we can get that the sum of the elements in the array is equal to all sets of input parameters, but these sets must already exist, for example, 11 = 2 + 2 + 2 + 2 + 3, 11 = 3 + 2 + 2 + 2 + 2 because the number of combinations needs to be calculated, in this case, we need a solution to remove all repeated combinations, where we can determine whether two arrays contain the same elements (even if their order is different ).
Here I use two solutions: 0. The most common solution is direct comparison. First, sort the two arrays and then compare them in sequence. The time complexity is O (lgn) 1. the multiplication of prime numbers is used, because the product result of any multiple prime numbers cannot be multiplied by any other multiple prime numbers. With this, we can give a, B, c, d is given a prime number, which is 2, 3, 5, and 7 in ascending order. Therefore, we need to calculate the numbers a, B, c, and d appearing in the two arrays and multiply them with these prime numbers respectively, if the calculation results of the two arrays are the same, the two arrays must be the same element. However, there is a possibility of removal. I use int to save the result of the product. Suppose N is equal to 100, a = 2, and the prime number of a is 2, then the product of the result is the power of 50 of 2. Apparently, overflow has exceeded, but overflow does not affect the correctness. However, here we use the prime number 2. If we happen to have more than 31 2 in a row, it will certainly overflow, the result of overflow is that the product is equal to 0, which leads to an error. Therefore, in my solution, 2 is not used, and 3 is used as the first prime number. of course, you can also use 1, but before determining whether the product is equal, you must first determine whether the number of elements in the two arrays is equal. 2. Using the counting method, the two arrays have the same elements, which is equivalent to the same number of occurrences of a, B, c, and d in the two arrays. Then I only need to save the number of these occurrences, which is obviously more efficient than the entire array, I also use the hashcode method of java to obtain the hash value of this object based on the number of occurrences of each element in the array, and then use the equals method to compare the number of occurrences one by one. This ensures correctness.
Test result: the input parameter here is 50-60 (because the recursive mode will be slow and unacceptable after 60), and the input array is [2, 3, 7]
1. recursion + removing duplicates using prime numbers:
value = 50, result = 37, cost = 14499 msvalue = 51, result = 39, cost = 20057 msvalue = 52, result = 40, cost = 29952 msvalue = 53, result = 41, cost = 40306 msvalue = 54, result = 43, cost = 59413 msvalue = 55, result = 44, cost = 81259 msvalue = 56, result = 46, cost = 110723 msvalue = 57, result = 47, cost = 160055 msvalue = 58, result = 49, cost = 227401 msvalue = 59, result = 50, cost = 334724 msvalue = 60, result = 52, cost = 443120 ms
2. Recursive + Count deduplication
value = 50, result = 37, cost = 14882 msvalue = 51, result = 39, cost = 21285 msvalue = 52, result = 40, cost = 29318 msvalue = 53, result = 41, cost = 40546 msvalue = 54, result = 43, cost = 71245 msvalue = 55, result = 44, cost = 82617 msvalue = 56, result = 46, cost = 111649 msvalue = 57, result = 47, cost = 157711 msvalue = 58, result = 49, cost = 211052 msvalue = 59, result = 50, cost = 292131 msvalue = 60, result = 52, cost = 408437 ms
3. Non-recursive mode + prime number deduplication
value = 150, result = 290, cost = 230 msvalue = 155, result = 308, cost = 121 msvalue = 160, result = 328, cost = 252 msvalue = 165, result = 348, cost = 75 msvalue = 170, result = 369, cost = 104 msvalue = 175, result = 390, cost = 161 msvalue = 180, result = 412, cost = 86 msvalue = 185, result = 434, cost = 108 msvalue = 190, result = 457, cost = 97 msvalue = 195, result = 481, cost = 132 msvalue = 200, result = 505, cost = 157 ms
4. Non-recursive mode + Count deduplication Solution
value = 150, result = 290, cost = 290 msvalue = 155, result = 308, cost = 101 msvalue = 160, result = 328, cost = 98 msvalue = 165, result = 348, cost = 86 msvalue = 170, result = 369, cost = 139 msvalue = 175, result = 390, cost = 449 msvalue = 180, result = 412, cost = 87 msvalue = 185, result = 434, cost = 185 msvalue = 190, result = 457, cost = 113 msvalue = 195, result = 481, cost = 167 msvalue = 200, result = 505, cost = 132 ms
From the test results, it is obvious that the non-recursive method has a performance of several orders of magnitude higher than the recursive method, and there are too many repeated computations in recursion. For de-duplication solutions, there is little difference between the two solutions. The counting method is more reliable. This method does not need to be correct. The program is more optimized: when using a non-recursive solution, you can place the computing of each number in multiple threads, but share the global cache. This should improve the performance. Supplement: in fact, this is similar to the idea of Fibonacci, so there is also a bottom-up solution, first initialize the number of the given array as the combination of the total number of results and cache, and then increase the calculation in turn, this solution saves some memory and can release a cache that is too far away from running. For example, the input is [2, 3, 3, 7]. Currently, the calculation result before 8 is no longer needed and can be released.
Additional: After testing found that multithreading for this problem does not seem to have any advantage, because we need to rely on the results of the N-K in the calculation of n, if the use of multithreading, then need to small to large computing, but in the calculation of N needs to rely on the results of N-k1, N-k2, N-K3, but these three worthy calculations may be allocated to other threads to complete, to ensure the correctness, You need to perform wait/notify operations, which will lead to computation in the case of poor caching. Therefore, the effect of Multithreading is worse.
Address: https://github.com/terry-chelsea/Algorithm/tree/master/src/tc/football Thank you for your correction ~~ |