Partition Equal Subset sum in Golang exceeding time limit - algorithm

I am running this program to solve partition sum problem using DP with memoization but this is exceeding time limit
Time Submitted Status Runtime Memory Language
08/30/2022 23:49 Time Limit Exceeded N/A N/A golang
what I am missing:-
Go playground
DP example function:-
func canPartition(nums []int) bool {
// sum & divide by 2, mod should be 0
sum := 0
fsum := 0
if len(nums) > 0 {
for i := range nums {
sum = sum + nums[i]
}
} else {
return false
}
if sum % 2 == 0 {
fsum = sum/2
} else {
return false
}
check := make(map[int]map[int]bool, 0)
// initial subset of sum is 0
check = map[int]map[int]bool{}
return recurse(nums, 0, 0, fsum, check)
}
func recurse(nums []int, index, sum, total int, check map[int]map[int]bool) bool {
if sum > total || index > len(nums)-1 {
return false
}
if sum == total {
return true
}
if _, ok := check[sum][index]; ok {
return check[sum][index]
}
check[sum] = map[int]bool{index:recurse(nums, index+1, sum+nums[index], total, check) || recurse(nums, index+1, sum, total, check)}
return check[sum][index]
}

This code have multiple issues:
when you use recursion, it makes all the memory to be allocated in a stack (which size is bounded), so if you will have many function call's, you'll eventually get a stack overflow error.
it looks like you are trying all possible combinations which takes O(n!). Modern CPU can handle about 10^9 operations per second, so if n > 13 you will count it forever.
It would be better to think about another solution. BUT this problem is NP full, and the best solution seems to be O(2^n) complexity, so you probably have too large testing set anyway.
Also it seems to be a good idea to reduce the same matching numbers (in pairs) as with this complexity even a small downgrade of n gives a nice exponential time win

Related

Recursive algorithm to find the largest odd element of an unsorted array?

I had this question on a midterm today and my brain completely melted and I had no clue how to write the pseudocode or even how to approach the problem. Any help would be appreciated.
This problem does not really call for a recursive solution, but if required, then use a divide-and-conquer approach: solve the problem for the left and right half of the array, then take the greatest of the two outcomes.
The recursion's base case occurs when the array has only one value: in that case verify whether it is odd. If so, return it, otherwise return some default value. I'll take minus infinity for that, meaning that if an array has no odd members, that will be the returned value.
Here is an implementation in JavaScript:
function greatestOdd(arr, first=0, last=arr.length-1) {
if (last == first) { // It's a single value
if (arr[first] % 2 == 1) return arr[first]; // Odd
else return -Infinity; // Even
}
let mid = (last + first) >> 1;
let a = greatestOdd(arr, first, mid);
let b = greatestOdd(arr, mid+1, last);
return Math.max(a, b);
}
console.log( greatestOdd([5,4,2,7,6,10]) ); // 7
You could simply traverse the array and get the largest odd number. Recursion is not needed but traversal can be done recursively like:
int findLargest(index, arr)
if ( index == arr.length - 1 )
if ( arr[index] % 2 != 0 ) return arr[index]
return MIN_VALUE
else
return arr[index] % 2 != 0 ? max(arr[index], findLargest(index + 1, arr))
: findLargest(index + 1, arr)
You visit each element once and time complexity is O(n) but this uses O(n) space and can lead to stackoverflow because intermediate results are needed on the stack for the final result.
For example:
max(arr[index], findLargest(index+1, arr)) is evaluated as:
max(arr[index], max(arr[index+1], findLargest(index+2, arr))) which is evaluated as :
max(arr[index], max(arr[index+1], max(arr[index+2], findLargest(index+3, arr))))
and so on...
The tail recursive version to avoid stack overflow:
int findLargestOdd(maxOdd, index, arr)
if ( index == arr.length-1) return maxOdd;
return arr[index+1] % 2 != 0
? return findLargestOdd(max(maxOdd, arr[index+1]), index+1, arr)
: return findLargestOdd(maxOdd, index+1, arr);
Here intermediate results needn't be stored on stack. You carry the result forward as : max(maxOdd, arr[index]) or maxOdd
You could call this function as :
return arr[0] % 2 != 0
? findLargestOdd(arr[0], 0, arr)
: findLargestOdd(MIN_VALUE, 0, arr)

Improving next_permutation algorithm

I have the following homework:
We have N works, which durations are: t1, t2, ..., tN, which's deadlines are d1, d2, ..., dN. If the works aren't done till the deadline, a penalty is given accordingly b1, b2, ..., bN. In what order should the jobs be done, that the penalty would be minimum?
I've written this code so far and it's working but I want to improve it by skipping unnecessary permutations. For example, I know that the jobs in order:
1 2 3 4 5 - will give me 100 points of penalty and if I change the order let's say like this:
2 1 ..... - it gives me instantly 120 penalty and from this moment I know I don't have to check all of the rest permutations which start with 2 1, I have to skip them somehow.
Here's the code:
int finalPenalty = -1;
bool z = true;
while(next_permutation(jobs.begin(), jobs.end(), compare) || z)
{
int time = 0;
int penalty = 0;
z = false;
for (int i = 0; i < verseNumber; i++)
{
if (penalty > finalPenalty && finalPenalty >= 0)
break;
time += jobs[i].duration;
if (time > jobs[i].deadline)
penalty += jobs[i].penalty;
}
if (finalPenalty < 0 || penalty < finalPenalty)
{
sortedJobs = jobs;
finalPenalty = penalty;
}
if (finalPenalty == 0)
break;
}
I think I should do this somewhere here:
if (penalty > finalPenalty && finalPenalty >= 0)
break;
But I'm not sure how to do this. It skips me one permutation here if the penalty is already higher, but it doesn't skip everything and it still does next_permutation. Any ideas?
EDIT:
I'm using vector and my job structure looks like this:
struct job
{
int ID;
int duration;
int deadline;
int penalty;
};
ID is given automatically when reading from file and the rest is read from file (for example: ID = 1, duration = 5, deadline = 10, penalty = 10)
If you are planning to use next_permutation function provided by STL, there is not much you can do.
Say the last k digits are redundant to check. If you will use next_permutation function, a simple, yet inefficient strategy you can use is calling next_permutation for k! times(i.e. number of permutations of those last k elements) and just not go through with computing their penalties, as you know they will be higher. (k! assumes there are not repetitions. if you have repetitions, you would need to take extra measures to be able to compute that) This would cost you O(k!n) operations on the worst case, as next_permutation has linear time complexity.
Let's consider how we can improve this. A sound strategy may be, once an inefficient setting is found, before calling next_permutation again, ordering those k digits in descending order so that the next call would effectively skip the inefficient portion of permutations that need not be checked. Consider the following example.
Say our method found 1 2 3 4 5 has a penalty of 100. Then, while computing 2 1 3 4 5 at the next step, if our method finds that we got a penalty higher than 100 only after computing 2 1, if could just sort 3 4 5 in descending order using sort along with your custom comparison mechanism, and just skip the rest of the loop, arriving at another next_permutation call, which would give you 2 1 4 3 5, the next sequence to continue.
Let's consider how much skipping costs. This method requires sorting those k digits and calling next_permutation, which has an overall time complexity of O(klogk + n). This is a huge improvement over the previous method which has O(k!n).
See below for an crude implementation of the method I propose as an improvement over your existing code. I had to use type auto as you did not provide the exact type for jobs. I also sorted then reversed those k digits, as you did not provide your comparison function and I wanted to emphasize that what I was doing was reversing the ascending order.
int finalPenalty = -1;
bool z = true;
while(next_permutation(jobs.begin(), jobs.end(), compare) || z)
{
int time = 0;
int penalty = 0;
z = false;
auto it = jobs.begin();
for (int i = 0; i < verseNumber; i++)
{
time += jobs[i].duration;
if (time > jobs[i].deadline)
{
penalty += jobs[i].penalty;
if(finalPenalty >= 0 && penalty > finalPenalty)
{
it++; // only the remaining jobs need to be sorted in reverse
sort(it, jobs.end(), compare);
reverse(it, jobs.end());
break;
}
}
it++;
}
if (finalPenalty < 0 || penalty < finalPenalty)
{
sortedJobs = jobs;
finalPenalty = penalty;
}
if (finalPenalty == 0)
break;
}

Return the number of elements of an array that is the most "expensive"

I recently stumbled upon an interesting problem, an I am wondering if my solution is optimal.
You are given an array of zeros and ones. The goal is to return the
amount zeros and the amount of ones in the most expensive sub-array.
The cost of an array is the amount of 1s divided by amount of 0s. In
case there are no zeros in the sub-array, the cost is zero.
At first I tried brute-forcing, but for an array of 10,000 elements it was far too slow and I ran out of memory.
My second idea was instead of creating those sub-arrays, to remember the start and the end of the sub-array. That way I saved a lot of memory, but the complexity was still O(n2).
My final solution that I came up is I think O(n). It goes like this:
Start at the beginning of the array, for each element, calculate the cost of the sub-arrays starting from 1, ending at the current index. So we would start with a sub-array consisting of the first element, then first and second etc. Since the only thing that we need to calculate the cost, is the amount of 1s and 0s in the sub-array, I could find the optimal end of the sub-array.
The second step was to start from the end of the sub-array from step one, and repeat the same to find the optimal beginning. That way I am sure that there is no better combination in the whole array.
Is this solution correct? If not, is there a counter-example that will show that this solution is incorrect?
Edit
For clarity:
Let's say our input array is 0101.
There are 10 subarrays:
0,1,0,1,01,10,01,010,101 and 0101.
The cost of the most expensive subarray would be 2 since 101 is the most expensive subarray. So the algorithm should return 1,2
Edit 2
There is one more thing that I forgot, if 2 sub-arrays have the same cost, the longer one is "more expensive".
Let me sketch a proof for my assumption:
(a = whole array, *=zero or more, +=one or more, {n}=exactly n)
Cases a=0* and a=1+ : c=0
Cases a=01+ and a=1+0 : conforms to 1*0{1,2}1*, a is optimum
For the normal case, a contains one or more 0s and 1s.
This means there is some optimum sub-array of non-zero cost.
(S) Assume s is an optimum sub-array of a.
It contains one or more zeros. (Otherwise its cost would be zero).
(T) Let t be the longest `1*0{1,2}+1*` sequence within s
(and among the equally long the one with with most 1s).
(Note: There is always one such, e.g. `10` or `01`.)
Let N be the number of 1s in t.
Now, we prove that always t = s.
By showing it is not possible to add adjacent parts of s to t if (S).
(E) Assume t shorter than s.
We cannot add 1s at either side, otherwise not (T).
For each 0 we add from s, we have to add at least N more 1s
later to get at least the same cost as our `1*0+1*`.
This means: We have to add at least one run of N 1s.
If we add some run of N+1, N+2 ... somewhere than not (T).
If we add consecutive zeros, we need to compensate
with longer runs of 1s, thus not (T).
This leaves us with the only option of adding single zeors and runs of N 1s each.
This would give (symmetry) `1{n}*0{1,2}1{m}01{n+m}...`
If m>0 then `1{m}01{n+m}` is longer than `1{n}0{1,2}1{m}`, thus not (T).
If m=0 then we get `1{n}001{n}`, thus not (T).
So assumption (E) must be wrong.
Conclusion: The optimum sub-array must conform to 1*0{1,2}1*.
Here is my O(n) impl in Java according to the assumption in my last comment (1*01* or 1*001*):
public class Q19596345 {
public static void main(String[] args) {
try {
String array = "0101001110111100111111001111110";
System.out.println("array=" + array);
SubArray current = new SubArray();
current.array = array;
SubArray best = (SubArray) current.clone();
for (int i = 0; i < array.length(); i++) {
current.accept(array.charAt(i));
SubArray candidate = (SubArray) current.clone();
candidate.trim();
if (candidate.cost() > best.cost()) {
best = candidate;
System.out.println("better: " + candidate);
}
}
System.out.println("best: " + best);
} catch (Exception ex) { ex.printStackTrace(System.err); }
}
static class SubArray implements Cloneable {
String array;
int start, leftOnes, zeros, rightOnes;
// optimize 1*0*1* by cutting
void trim() {
if (zeros > 1) {
if (leftOnes < rightOnes) {
start += leftOnes + (zeros - 1);
leftOnes = 0;
zeros = 1;
} else if (leftOnes > rightOnes) {
zeros = 1;
rightOnes = 0;
}
}
}
double cost() {
if (zeros == 0) return 0;
else return (leftOnes + rightOnes) / (double) zeros +
(leftOnes + zeros + rightOnes) * 0.00001;
}
void accept(char c) {
if (c == '1') {
if (zeros == 0) leftOnes++;
else rightOnes++;
} else {
if (rightOnes > 0) {
start += leftOnes + zeros;
leftOnes = rightOnes;
zeros = 0;
rightOnes = 0;
}
zeros++;
}
}
public Object clone() throws CloneNotSupportedException { return super.clone(); }
public String toString() { return String.format("%s at %d with cost %.3f with zeros,ones=%d,%d",
array.substring(start, start + leftOnes + zeros + rightOnes), start, cost(), zeros, leftOnes + rightOnes);
}
}
}
If we can show the max array is always 1+0+1+, 1+0, or 01+ (Regular expression notation then we can calculate the number of runs
So for the array (010011), we have (always starting with a run of 1s)
0,1,1,2,2
so the ratios are (0, 1, 0.3, 1.5, 1), which leads to an array of 10011 as the final result, ignoring the one runs
Cost of the left edge is 0
Cost of the right edge is 2
So in this case, the right edge is the correct answer -- 011
I haven't yet been able to come up with a counterexample, but the proof isn't obvious either. Hopefully we can crowd source one :)
The degenerate cases are simpler
All 1's and 0's are obvious, as they all have the same cost.
A string of just 1+,0+ or vice versa is all the 1's and a single 0.
How about this? As a C# programmer, I am thinking we can use something like Dictionary of <int,int,int>.
The first int would be use as key, second as subarray number and the third would be for the elements of sub-array.
For your example
key|Sub-array number|elements
1|1|0
2|2|1
3|3|0
4|4|1
5|5|0
6|5|1
7|6|1
8|6|0
9|7|0
10|7|1
11|8|0
12|8|1
13|8|0
14|9|1
15|9|0
16|9|1
17|10|0
18|10|1
19|10|0
20|10|1
Then you can run through the dictionary and store the highest in a variable.
var maxcost=0
var arrnumber=1;
var zeros=0;
var ones=0;
var cost=0;
for (var i=1;i++;i<=20+1)
{
if ( dictionary.arraynumber[i]!=dictionary.arraynumber[i-1])
{
zeros=0;
ones=0;
cost=0;
if (cost>maxcost)
{
maxcost=cost;
}
}
else
{
if (dictionary.values[i]==0)
{
zeros++;
}
else
{
ones++;
}
cost=ones/zeros;
}
}
This will be log(n^2), i hope and u just need 3n size of memory of the array?
I think we can modify the maximal subarray problem to fit to this question. Here's my attempt at it:
void FindMaxRatio(int[] array, out maxNumOnes, out maxNumZeros)
{
maxNumOnes = 0;
maxNumZeros = 0;
int numOnes = 0;
int numZeros = 0;
double maxSoFar = 0;
double maxEndingHere = 0;
for(int i = 0; i < array.Size; i++){
if(array[i] == 0) numZeros++;
if(array[i] == 1) numOnes++;
if(numZeros == 0) maxEndingHere = 0;
else maxEndingHere = numOnes/(double)numZeros;
if(maxEndingHere < 1 && maxEndingHere > 0) {
numZeros = 0;
numOnes = 0;
}
if(maxSoFar < maxEndingHere){
maxSoFar = maxEndingHere;
maxNumOnes = numOnes;
maxNumZeros = numZeros;
}
}
}
I think the key is if the ratio is less then 1, we can disregard that subsequence because
there will always be a subsequence 01 or 10 whose ratio is 1. This seemed to work for 010011.

What is the best way to recursively generate all binary strings of length n?

I'm looking for a good (easy to implement, intuitive, etc.) recursive method of generating all binary strings of length n, where 1 <= n <= 35.
I would appreciate ideas for a pseudo-code algorithm (no language-specific tricks).
LE: okay, I did go overboard with the upper limit. My intention was to avoid solutions that use the binary representation of a counter from 1 to 1 << n.
Here's an example of recursion in C++.
vector<string> answer;
void getStrings( string s, int digitsLeft )
{
if( digitsLeft == 0 ) // the length of string is n
answer.push_back( s );
else
{
getStrings( s + "0", digitsLeft - 1 );
getStrings( s + "1", digitsLeft - 1 );
}
}
getStrings( "", n ); // initial call
According to the Divide et Impera paradigm, the problem of generating all binary strings of length n can be splitted in two subproblems: the problem of printing all binary strings of lenght n-1 preceeded by a 0 and the one of printing all binary strings of lenght n-1 preceeded by a 1. So the following pseudocode solves the problem:
generateBinary(length, string)
if(length > 0)
generateBinary(length-1, string + "0")
generateBinary(length-1, string + "1")
else
print(string)
def genBins(n):
"""
generate all the binary strings with n-length
"""
max_int = '0b' + '1' * n
for i in range(0, int(max_int, 2)+1, 1):
yield str(format(i, 'b').zfill(n))
if __name__ == '__main__':
print(list(genBins(5)))
The problem you have can be solved with a Backtracking algorithm.
Pseudo-code for such an algorithm is:
fun(input, n)
if( base_case(input, n) )
//print result
else
//choose from pool of choices
//explorer the rest of choices from what's left
//unchoose
Implementation:
Base case: we want to print our result string when its size is equal to n
Recursive case:
our pool of choices consists of 0 and 1
choosing in this case means take 0 or 1 and add it to the input as last character
explore by recursing, where we pass the new input value from the choose step until base case is reached
un-choosing in this case means remove the last character
function binary(n) {
binaryHelper('', n);
}
function binaryHelper(str, n) {
if (str.length === n) {
//base case
console.log(str); //print string
} else {
for (let bit = 0; bit < 2; bit++) {
str = str + bit; // choose
binaryHelper(str, n); // explore
str = str.slice(0, -1); // un-choose
}
}
}
console.log('Size 2 binary strings:');
binary(2);
console.log('Size 3 binary strings:');
binary(3);
You can re-write the code above like this, where you choose & un-choose by stateless transition from one loop iteration to another. This is less intuitive though.
function binary(n) {
binaryHelper('', n);
}
function binaryHelper(str, n) {
if(str.length === n) {
console.log(str);
} else {
for(let bit = 0; bit < 2; bit++) {
binaryHelper(str+bit, n);
}
}
}
console.log('Size 2 binary strings:');
binary(2);
console.log('Size 3 binary strings:');
binary(3);

How do I find the nearest prime number?

Is there any nice algorithm to find the nearest prime number to a given real number? I only need to search within the first 100 primes or so.
At present, I've a bunch of prime numbers stored in an array and I'm checking the difference one number at a time (O(n)?).
Rather than a sorted list of primes, given the relatively small range targetted, have an array indexed by all the odd numbers in the range (you know there are no even primes except the special case of 2) and containing the closest prime. Finding the solution becomes O(1) time-wise.
I think the 100th prime is circa 541. an array of 270 [small] ints is all that is needed.
This approach is particularly valid, given the relative high density of primes (in particular relative to odd numbers), in the range below 1,000. (As this affects the size of a binary tree)
If you only need to search in the first 100 primes or so, just create a sorted table of those primes, and do a binary search. This will either get you to one prime number, or a spot between two, and you check which of those is closer.
Edit: Given the distribution of primes in that range, you could probably speed things up (a tiny bit) by using an interpolation search -- instead of always starting at the middle of the table, use linear interpolation to guess at a more accurate starting point. The 100th prime number should be somewhere around 250 or so (at a guess -- I haven't checked), so if (for example) you wanted the one closest to 50, you'd start about 1/5th of the way into the array instead of halfway. You can pretty much treat the primes as starting at 1, so just divide the number you want by the largest in your range to get a guess at the starting point.
Answers so far are rather complicated, given the task in hand. The first hundred primes are all less then 600. I would create an array of size 600 and place in each the value of the nearest prime to that number. Then, given a number to test, I would round it both up and down using the floor and ceil functions to get one or two candidate answers. A simple comparison with the distances to these numbers will give you a very fast answer.
The simplest approach would be to store the primes in a sorted list and modify your algorithm to do a binary search.
The standard binary search algorithm would return null for a miss, but it should be straight-forward to modify it for your purposes.
The fastest algorithm? Create a lookup table with p[100]=541 elements and return the result for floor(x), with special logic for x on [2,3]. That would be O(1).
You should sort your number in array then you can use binary search. This algorithm is O(log n) performance in worst case.
public static boolean p(int n){
for(int i=3;i*i<=n;i+=2) {
if(n%i==0)
return false;
}
return n%2==0? false: true; }
public static void main(String args[]){
String n="0";
int x = Integer.parseInt(n);
int z=x;
int a=0;
int i=1;
while(!p(x)){
a = i*(int)Math.pow(-1, i);
i++;
x+=a;
}
System.out.println( (int) Math.abs(x-z));}
this is for n>=2.
In python:
>>> def nearest_prime(n):
incr = -1
multiplier = -1
count = 1
while True:
if prime(n):
return n
else:
n = n + incr
multiplier = multiplier * -1
count = count + 1
incr = multiplier * count
>>> nearest_prime(3)
3
>>> nearest_prime(4)
3
>>> nearest_prime(5)
5
>>> nearest_prime(6)
5
>>> nearest_prime(7)
7
>>> nearest_prime(8)
7
>>> nearest_prime(9)
7
>>> nearest_prime(10)
11
<?php
$N1Diff = null;
$N2Diff = null;
$n1 = null;
$n2 = null;
$number = 16;
function isPrime($x) {
for ($i = 2; $i < $x; $i++) {
if ($x % $i == 0) {
return false;
}
}
return true;
}
for ($j = $number; ; $j--) {
if( isPrime($j) ){
$N1Diff = abs($number - $j);
$n1 = $j;
break;
}
}
for ($j = $number; ; $j++) {
if( isPrime($j) ){
$N2Diff = abs($number - $j);
$n2 = $j;
break;
}
}
if($N1Diff < $N2Diff) {
echo $n1;
} else if ($N1Diff2 < $N1Diff ){
echo $n2;
}
If you want to write an algorithm, A Wikipedia search for prime number led me to another article on the Sieve of Eratosthenes. The algorithm looks a bit simple and I'm thinking a recursive function would suit it well imo. (I could be wrong about that.)
If the array solution isn't a valid solution for you (it is the best one for your scenario), you can try the code below. After the "2 or 3" case, it will check every odd number away from the starting value until it finds a prime.
static int NearestPrime(double original)
{
int above = (int)Math.Ceiling(original);
int below = (int)Math.Floor(original);
if (above <= 2)
{
return 2;
}
if (below == 2)
{
return (original - 2 < 0.5) ? 2 : 3;
}
if (below % 2 == 0) below -= 1;
if (above % 2 == 0) above += 1;
double diffBelow = double.MaxValue, diffAbove = double.MaxValue;
for (; ; above += 2, below -= 2)
{
if (IsPrime(below))
{
diffBelow = original - below;
}
if (IsPrime(above))
{
diffAbove = above - original;
}
if (diffAbove != double.MaxValue || diffBelow != double.MaxValue)
{
break;
}
}
//edit to your liking for midpoint cases (4.0, 6.0, 9.0, etc)
return (int) (diffAbove < diffBelow ? above : below);
}
static bool IsPrime(int p) //intentionally incomplete due to checks in NearestPrime
{
for (int i = 3; i < Math.Sqrt(p); i += 2)
{
if (p % i == 0)
return false;
}
return true;
}
Lookup table whit size of 100 bytes; (unsigned chars)
Round real number and use lookup table.
Maybe we can find the left and right nearest prime numbers, and then compare to get the nearest one. (I've assumed that the next prime number shows up within next 10 occurrences)
def leftnearestprimeno(n):
n1 = n-1
while(n1 >= 0):
if isprime(n1):
return n1
else:
n1 -= 1
return -1
def rightnearestprimeno(n):
n1 = n+1
while(n1 < (n+10)):
if isprime(n1):
return n1
else:
n1 += 1
return -1
n = int(input())
a = leftnearestprimeno(n)
b = rightnearestprimeno(n)
if (n - a) < (b - n):
print("nearest: ", a)
elif (n - a) > (b - n):
print("nearest: ", b)
else:
print("nearest: ", a) #in case the difference is equal, choose min
#value
Simplest answer-
Every prime number can be represented in the form (6*x-1 and 6*X +1) (except 2 and 3).
let number is N.divide it with 6.
t=N/6;
now
a=(t-1)*6
b=(t+1)*6
and check which one is closer to N.

Resources