Minimum Size Subarray Sum with sorting - arrays
The Minimum Size Subarray Sum problem:
given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. If there isn't one, return 0 instead.
For example, given the array [2,3,1,2,4,3] and s = 7,
the subarray [4,3] has the minimal length under the problem constraint.
The following is my solution:
public int minSubArrayLen(int s, int[] nums) {
long sum = 0;
int a = 0;
if (nums.length < 1)
return 0;
Arrays.sort(nums);
for (int i = nums.length-1; i >= 0; i--) {
sum += nums[i];
a++;
if (sum>=s)
break;
}
if (sum < s) {
return 0;
}
return a;
}
This solution was not accepted because it did not pass the following test case:
697439
[5334,6299,4199,9663,8945,3566,9509,3124,6026,6250,7475,5420,9201,9501,38,5897,4411,6638,9845,161,9563,8854,3731,5564,5331,4294,3275,1972,1521,2377,3701,6462,6778,187,9778,758,550,7510,6225,8691,3666,4622,9722,8011,7247,575,5431,4777,4032,8682,5888,8047,3562,9462,6501,7855,505,4675,6973,493,1374,3227,1244,7364,2298,3244,8627,5102,6375,8653,1820,3857,7195,7830,4461,7821,5037,2918,4279,2791,1500,9858,6915,5156,970,1471,5296,1688,578,7266,4182,1430,4985,5730,7941,3880,607,8776,1348,2974,1094,6733,5177,4975,5421,8190,8255,9112,8651,2797,335,8677,3754,893,1818,8479,5875,1695,8295,7993,7037,8546,7906,4102,7279,1407,2462,4425,2148,2925,3903,5447,5893,3534,3663,8307,8679,8474,1202,3474,2961,1149,7451,4279,7875,5692,6186,8109,7763,7798,2250,2969,7974,9781,7741,4914,5446,1861,8914,2544,5683,8952,6745,4870,1848,7887,6448,7873,128,3281,794,1965,7036,8094,1211,9450,6981,4244,2418,8610,8681,2402,2904,7712,3252,5029,3004,5526,6965,8866,2764,600,631,9075,2631,3411,2737,2328,652,494,6556,9391,4517,8934,8892,4561,9331,1386,4636,9627,5435,9272,110,413,9706,5470,5008,1706,7045,9648,7505,6968,7509,3120,7869,6776,6434,7994,5441,288,492,1617,3274,7019,5575,6664,6056,7069,1996,9581,3103,9266,2554,7471,4251,4320,4749,649,2617,3018,4332,415,2243,1924,69,5902,3602,2925,6542,345,4657,9034,8977,6799,8397,1187,3678,4921,6518,851,6941,6920,259,4503,2637,7438,3893,5042,8552,6661,5043,9555,9095,4123,142,1446,8047,6234,1199,8848,5656,1910,3430,2843,8043,9156,7838,2332,9634,2410,2958,3431,4270,1420,4227,7712,6648,1607,1575,3741,1493,7770,3018,5398,6215,8601,6244,7551,2587,2254,3607,1147,5184,9173,8680,8610,1597,1763,7914,3441,7006,1318,7044,7267,8206,9684,4814,9748,4497,2239]
The expected answer is 132 but my output was 80.
Does anyone have any idea what went wrong with my algorithm/code?
I will simply explain the flaw in the logic rather giving the correct logic to handle the problem statement
You are taking the numbers in a specific sequence and then adding them for comparison. Quite easily the case can be different where you take numbers in random order to get the exact sum.
For example [2,3,1,2,4,3] and s = 7.
Based on your logic
Step 1-> Sort the numbers and you get [1,2,2,3,3,4]
Step 2-> You pick last 2 number (3,4) to get your sum 7
Lets change the sum to 8
From Step 2-> You get 3+3+4 = 10 so u break out of the loop. After this step you return a = 2
Flaw here is 4+3+1 also makes 8 something your logic skips.
Same way 3+3+2 is also possible solution to achieve 8.
You sorting the array is first flaw in the logic itself. If you consider subarray of existing arrangement, sorting changes the arrangement therefore you will never be able to get the expected solution.
Related
How to regroup into two arrays with equal sum?
I encountered a question that I couldn't solve during my algorithm interview. The question goes: Given an array of length n, where n is an even number, regroup the elements in the array into two smaller arrays, each with equal length (n/2), with the condition that the sum of each of these smaller arrays is equal. If this cannot be achieved, return -1. Eg. Input: [1,1,1,2,3,3,3,6] Output: [[1,1,2,6], [1,3,3,3]] Eg. Input: [1,4,5,6] Output: -1 I was thinking about randomly initializing two subarrays and then interchanging two elements so that their difference is at least half the total differences in the sum of two arrays. However, I had trouble coming up with a criterion that would dictate the scenario when the input is illegitimate, and the answer should be -1. Thanks for any help and hints!
OK, I will just post my dumb solution here. I work out all the possible subsequences with sum equal to half of the total sum. Then, check if there is any subsequence with length equal to half of the length of the array. If anyone comes up with a faster solution, please let me know :) from collections import Counter def partition(nums): if sum(nums) % 2 != 0: # if the sum is an odd number it's impossible return -1 nums.sort() target = sum(nums) / 2 out = [] ct = Counter(nums) def dp(cand): # first find out all the sub-sequence with sum equal to n/2 if sum(cand) == target: out.append(cand) remain = target - sum(cand) for i, number in enumerate(nums): if number > remain: break if (cand and number < cand[-1]) or ct[number] == 0: continue if i >= 1 and nums[i - 1] == nums[i]: continue ct[number] -= 1 dp([*cand, number]) ct[number] += 1 dp([]) for sub_array in out: if len(sub_array) != len(nums) / 2: continue # check if there is any subsequence with exactly half length another_array = [] stats = Counter(sub_array) for num, count in ct.items(): another_array += [num] * (count - stats[num]) return [another_array, sub_array] return -1
let sum=0; for (int i=0;i<x.length;i++) {sum=sum+i} if (sum%2!=0){ return - 1;} else { //do your code here // } If the sum of the array doesn't sum up to even number, return - 1. Hope this address your question
Rebuild an array of integers after summing the digits of each element
We have an strictly increasing array of length n ( 1 < n < 500) . We sum the digits of each element to create a new array with each elements values is in range 1 to 500.The task is to rebuild the old array from the new one. since there might be more than one answer, we want the answers with the minimum value of the last element. Example: 3 11 23 37 45 123 =>3 2 5 10 9 6 now from the second array, we can rebuild the original array in many different ways for instance: 12 20 23 37 54 60 from all the possible combinations, we need the one we minimum last element. My Thoughts so far: The brute force way is to find all possible permutations to create each number and then create all combinations possible of all numbers of the second array and find the combination with minimum last element. It is obvious that this is not a good choice. Using this algorithm(with exponential time!) we can create all possible permutations of digits that sum to a number in the second arrays. Note that we know the original elements were less than 500 so we can limit the death of search of the algorithm. One way I thought of that might find the answer faster is to: start from the last element in the new arrays and find all possible numbers that their digit sum resulted this element. Then try to use the smallest amount in the last step for this element. Now try to do the same with the second to last element. If the minimum permutation value found for the second to last element is bigger than the one found for the last element, backtrack to the last element and try a larger permutation. Do this until you get to the first element. I think this is a greed solution but I'm not very sure about the time complexity. Also I want to know is there a better solution for this problem? like using dp?
For simplicity, let's have our sequence 1-based and the input sequence is called x. We will also use an utility function, which returns the sum of the digits of a given number: int sum(int x) { int result = 0; while (x > 0) { result += x % 10; x /= 10; } return result; } Let's assume that we are at index idx and try to set there some number called value (given that the sum of digits of value is x[idx]). If we do so, then what could we say about the previous number in the sequence? It should be strictly less than value. So we already have a state for a potential dp approach - [idx, value], where idx is the index where we are currently at and value denotes the value we are trying to set on this index. If the dp table holds boolean values, we will know we have found an answer if we have found a suitable number for the first number in the sequence. Therefore, if there is a path starting from the last row in the dp table and ends at row 0 then we'll know we have found an answer and we could then simply restore it. Our recurrence function will be something like this: f(idx, value) = OR {dp[idx - 1][value'], where sumOfDigits(value) = x[idx] and value' < value} f(0, *) = true Also, in order to restore the answer, we need to track the path. Once we set any dp[idx][value] cell to be true, then we can safe the value' to which we would like to jump in the previous table row. Now let's code that one. I hope the code is self-explanatory: boolean[][] dp = new boolean[n + 1][501]; int[][] prev = new int[n + 1][501]; for (int i = 0; i <= 500; i++) { dp[0][i] = true; } for (int idx = 1; idx <= n; idx++) { for (int value = 1; value <= 500; value++) { if (sum(value) == x[idx]) { for (int smaller = 0; smaller < value; smaller++) { dp[idx][value] |= dp[idx - 1][smaller]; if (dp[idx][value]) { prev[idx][value] = smaller; break; } } } } } The prev table only keeps information about which is the smallest value', which we can use as previous to our idx in the resulting sequence. Now, in order to restore the sequence, we can start from the last element. We would like it to be minimal, so we can find the first one that has dp[n][value] = true. Once we have such element, we then use the prev table to track down the values up to the first one: int[] result = new int[n]; int idx = n - 1; for (int i = 0; i <= 500; i++) { if (dp[n][i]) { int row = n, col = i; while (row > 0) { result[idx--] = col; col = prev[row][col]; row--; } break; } } for (int i = 0; i < n; i++) { out.print(result[i]); out.print(' '); } If we apply this on an input sequence: 3 2 5 10 9 6 we get 3 11 14 19 27 33 The time complexity is O(n * m * m), where n is the number of elements we have and m is the maximum possible value that an element could hold. The space complexity is O(n * m) as this is dominated by the size of the dp and prev tables.
We can use a greedy algorithm: proceed through the array in order, setting each element to the least value that is greater than the previous element and has digits with the appropriate sum. (We can just iterate over the possible values and check the sums of their digits.) There's no need to consider any greater value than that, because increasing a given element will never make it possible to decrease a later element. So we don't need dynamic programming here. We can calculate the sum of the digits of an integer m in O(log m) time, so the whole solution takes O(b log b) time, where b is the upper bound (500 in your example).
Smallest sum of a sequence of numbers in the array. Do not need code [closed]
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers. This question does not appear to be about programming within the scope defined in the help center. Closed 7 years ago. Improve this question Write a function called smallest_sum_sequence() that accepts an array of signed integers and the number of items in the array as arguments, and returns the smallest sum of a sequence of numbers in the array. A sequence is defined as a single item or multiple items that are in adjacent memory locations. This is obviously homework, I do not need anyone to write the code for me just an explanation of what they actually are looking for, as it is worded weirdly in my opinion. I think what they are wanting is: Given an array and the total items in the array. Have the user input a sequence of values for the array ( array[7] -> array[9] ) return smallest sum Then determine the smallest sum? Is that supposed to be the smallest value or the smallest combination of items? The first sounds too easy and the second doesn't make sense even if you have negatives. Am looking for any sort of enlightenment.
So a sequence is a set of any number of adjacent numbers in an array. In a set like [A B C D E] Any individual could be an answer. Or [A B] could be an answer. Or [A B C]. Or [C D E]. Or even [A B C D E]. But, definitely not [A D E] since A is not adjacent to D in the original set. Easy. Now you have to write code that will compare the sum of the values in every possible adjacent sequence, in any set of numbers (given the size of that set beforehand).
Edited as the prior answer was wrong! This is how I understand it. Assume you have an array of signed integers, called A, consisting of, say, <3, 4, 5>. So n = 3, the length of the array. Your sequence is defined to be a single (or multiple) items in adjacent memory locations. So A[0] and A[1] would be a sequence as they are in adjacent memory locations, but A[0] and A[2] wouldn't be. You call your function: smallest_sum_sequence(A, n) with A and n as above. So your sequences are: + of length 1) <3>, <4>, <5> + of length 2) <3,4>, <4,5> + of length 3) <3, 4, 5> Hence your function should return 3 in this case.
You have to sum each int with the next one and find the min of the sum You can walk like this int min = INT_MAX; for (i = 0; i < len; i++) { sum = array[i]; min = MIN(min, sum); for (j = i + 1; j < len ; j++ ) { sum += array[j]; min = MIN(min, sum); } }
With an array of signed integers it is possible that a larger sequence produces a smaller sum than a single number or a pair. To find out you need to produce all possible sequences: Start with first number alone, then first and second, then first, second and third. Then start with second number ... Then the sum of each sequence. Return smallest sum (and probably the matching sequence)
Let's look closely at the requirements: Write a function ... smallest_sum_sequence() that accepts (1) an array of signed integers and (2) the number of items in the array as arguments, and (3) returns the smallest sum of a sequence of numbers in the array. A sequence is defined as a single item or multiple items ... in adjacent memory locations. Taking them one at a time, you know you will write a function that accepts an array of type int and then number of items (won't be negative, so size_t is a good type). Since it must return a smallest sum, the return type of the function can be int as well: int smallest_sum_sequence (int *a, size_t n) { ... return ssum; } That is the basic framework for your function. The next issue to address is the smallest sum. Since you are told you are accepting an array of signed values, you must presume that the values within the array can be both negative and positive numbers. You are next told the sum of the smallest sequence can be be derived from a single or multiple adjacent values? What I interpret this to mean is that you must keep 2 running values. (1) the minimum value in the array; and (2) a sum of the smallest sequences. In the arguments you get the number of elements in the array providing you with an easy means to iterate over the array itself: int i = 0; int min = INT_MAX; /* largest possible minimum number */ int ssum = INT_MAX; /* largest possible smallest sum */ for (i = 0; i < n; i++) { min = a[i] < min ? a[i] : min; if (i > 0) { int tssum = 0; /* temporary smallest sum */ /* test adjacent values { if adjacent: tssum += a[i]; { if no longer adjacent { compare tssum < ssum, if so ssum = tssum; } } } */ } } In your first iteration over the array, you have found min the minimum single value and ssum the sum of the smallest sequence. Now all that is left is the return: return min < ssum ? min : ssum; That is my impression of what the logic asked for. You may have to adjust the logic of the pseudo-code and you need to figure out how to identify a sequence start/end, but this should at least give you an outline of one way to approach it. Good luck.
find the largest ten numbers in an array in C
I have an array of int (the length of the array can go from 11 to 500) and i need to extract, in another array, the largest ten numbers. So, my starting code could be this: arrayNumbers[n]; //array in input with numbers, 11<n<500 int arrayMax[10]; for (int i=0; i<n; i++){ if(arrayNumbers[i] .... //here, i need the code to save current int in arrayMax correctly } //at the end of cycle, i want to have in arrayMax, the ten largest numbers (they haven't to be ordered) What's the best efficient way to do this in C?
Study maxheap. Maintain a heap of size 10 and ignore all spilling elements. If you face a difficulty please ask. EDIT: If number of elements are less than 20, find n-10 smallest elements and rest if the numbers are top 10 numbers. Visualize a heap here EDIT2: Based on comment from Sleepy head, I searched and found this (I have not tested). You can find kth largest element (10 in this case) in )(n) time. Now in O(n) time, you can find first 10 elements which are greater than or equal to this kth largest number. Final complexity is linear.
Here is a algo which solves in linear time: Use the selection algorithm, which effectively find the k-th element in a un-sorted array in linear time. You can either use a variant of quick sort or more robust algorithms. Get the top k using the pivot got in step 1.
This is my idea: insert first 10 elements of your arrayNum into arrMax. Sort those 10 elements arrMax[0] = min , arrMax[9] = max. then check the remaining elements one by one and insert every possible candidate into it's right position as follow (draft): int k, r, p; for (int k = 10; k < n; k++) { r = 0; while(1) { if (arrMax[r] > arrNum[k]) break; // position to insert new comer else if (r == 10) break; // don't exceed length of arrMax else r++; // iteration } if (r != 0) // no need to insert number smaller than all members { for (p=0; p<r-1; p++) arrMax[p]=arrMax[p+1]; // shift arrMax to make space for new comer arrMax[r-1] = arrNum[k]; // insert new comer at it's position } } // done!
Sort the array and insert Max 10 elements in another array
you can use the "select" algorithm which finds you the i-th largest number (you can put any number you like instead of i) and then iterate over the array and find the numbers that are bigger than i. in your case i=10 of course..
The following example can help you. it arranges the biggest 10 elements of the original array into arrMax assuming you have all positive numbers in the original array arrNum. Based on this you can work for negative numbers also by initializing all elements of the arrMax with possible smallest number. Anyway, using a heap of 10 elements is a better solution rather than this one. void main() { int arrNum[500]={1,2,3,21,34,4,5,6,7,87,8,9,10,11,12,13,14,15,16,17,18,19,20}; int arrMax[10]={0}; int i,cur,j,nn=23,pos; clrscr(); for(cur=0;cur<nn;cur++) { for(pos=9;pos>=0;pos--) if(arrMax[pos]<arrNum[cur]) break; for(j=1;j<=pos;j++) arrMax[j-1]=arrMax[j]; if(pos>=0) arrMax[pos]=arrNum[cur]; } for(i=0;i<10;i++) printf("%d ",arrMax[i]); getch(); }
When improving efficiency of an algorithm, it is often best (and instructive) to start with a naive implementation and improve it. Since in your question you obviously don't even have that, efficiency is perhaps a moot point. If you start with the simpler question of how to find the largest integer: Initialise largest_found to INT_MIN Iterate the array with : IF value > largest_found THEN largest_found = value To get the 10 largest, you perform the same algorithm 10 times, but retaining the last_largest and its index from the previous iteration, modify the largest_found test thus: IF value > largest_found && value <= last_largest_found && index != last_largest_index THEN largest_found = last_largest_found = value last_largest_index = index Start with that, then ask yourself (or here) about efficiency.
Algorithm - Find pure numbers
Description: A positive integer m is said to a pure number if and only if m can be expressed as q-th power of a prime p (q >= 1). Here your job is easy, for a given positive integer k, find the k-th pure number. Input: The input consists of multiple test cases. For each test case, it contains a positive integer k (k<5,000,000). Process to end of file. Output: For each test case, output the k-th pure number in a single line. If the answer is larger than 5,000,000, just output -1. Sample input: 1 100 400000 Sample output: 2 419 -1 Original page: http://acm.whu.edu.cn/learn/problem/detail?problem_id=1092 Can anyone give me some suggestion on the solution to this?
You've already figured out all the pure numbers, which is the tricky part. Sort the ones less than 5 million and then look up each input in turn in the resulting array. To optimize you need to efficiently find all primes up to 5 million (note q >= 1 in the problem description: every prime is a pure number), for which you will want to use some kind of sieve (sieve of Erathosthenes will do, look it up). You could probably adapt the sieve to leave in powers of primes, but I expect that it would not take long to sieve normally and then put the powers back in. You only have to compute powers of primes p where p <= the square root of 5 million, which is 2236, so this shouldn't take long compared with finding the primes. Having found the numbers with a sieve, you no longer need to sort them, just copy the marked values from the sieve to a new array. Having now looked at your actual code: your QuickSort routine is suspect. It performs badly for already-sorted data and your array will have runs of sorted numbers in it. Try qsort instead, or if you're supposed to do everything yourself then you need to read up on pivot choice for quicksort.
Try following approach: static void Main(string[] args) { int max = 5000000; int[] dp = new int[max]; for (int i = 2; i < max; i++) { if (dp[i] == 0) { long t = i; while (t < max) { dp[t] = 1; t *= i; } int end = max / i; for (int j = 2; j < end; j++) if (dp[i * j] == 0) dp[i * j] = 2; } } int[] result = new int[348978]; int pointer = 1; for (int i = 2; i < max; i++) { if (dp[i] == 1) result[pointer++] = i; } } Into array as "1" marked pure numbers. As "2" marked non pure(prime) numbers. For each output check array ranges if it inside output result[index] if not output should be -1.