So recently I stumbled across a query i.e.
code 1:
for(long i = 1; i <= m; i++) {
long j = (fullsum - 2*(sum -i))/2;
if(j >= m+1 && j <=n) {
swaps++;
}
}
code 2:
for(long i = 1; i <= m; i++) {
for(long j = m+1; j <=n ; j++) {
if(sum - i + j == fullsum - sum -j + i) {
swaps++;
break;
}
}
}
Where fullsum = n*(n+1)/2, sum = m*(m+1)/2
1 <= N <= 10^9
1 <= M < N
Now my question here is that both the codes seem identical to me(logic wise) but Code 2 is giving correct output while code 1 is not.
Can anyone please tell me the difference between the codes, further why code2 is giving the correct output while code1 is not and what is the correct way of implementing code 1?
Rewriting if(sum - i + j == fullsum - sum -j + i), we get
if(2*j == fullsum - 2*(sum-i))
In the first code, the value you are assigning to j is
long j = (fullsum - 2*(sum -i))/2;
The issue is pretty clear: division truncation is causing the incorrect results. Let's say that fullsum - 2*(sum-i) = 45 for some case, and j=22. Now, the second condition will be false, since 2*j != fullsum - 2*(sum-i).
However, for the first condition, (fullsum - 2*(sum -i))/2 has a value of 45/2 = 22 (floor division), so the condition j = (fullsum - 2*(sum -i))/2 will be counted as a valid result when it shouldn't have been.
This is the recursive function
def integerPartition(m, n):
if(n==0):
return 0
if(m ==0):
return 1
if(m<0):
return 0
return integerPartition(m,n-1) + integerPartition(m-n,n)
and this is what i have done in c++
// n -> no. of persons
// m -> amount of money to be distributed
// dp table of order (n+1)*(m+1)
long long int dp[n+1][m+1] ;
//initializing values to 0
for(i = 0; i<=n ; i++)
for(j = 0; j<= m ; j++)
dp[i][j] = 0;
Print(n,m,dp);
cout << "\n";
//Case 1 - if there is no persons i.e n = 0 answer will be 0
//Case 2 - if there is no money i.e. m = 0 there is only 1 way answer will be 1
for ( i = 1; i<= n ; i++ )
dp[i][0] = 1;
dp[i][i] = 1;
Print(n,m,dp);
for ( i = 1; i<= n ; i++){
for ( j = 1; j<= m ; j++){
dp[i][j] = dp[i][j-1] ;
if(i>=j){
dp[i][j] += dp[i-j][j];
}
// else if(i==j){
// dp[i][j] += 1;
// }
}
}
but the answers i am getting are not matching with the recursive one i don't understand what am i missing if anyone can please help me to correct i will be thankful since i have just started with dynamic programming i really am not able to figure it out
Some issues:
You seem to use non-local variables for your for loops. This is bad practice and can lead to errors that are difficult to debug. Instead
do for (int i = 1; ...etc.
dp[i][i] = 1; is not part of the for loop. You would have detected this if you would have defined i only as a variable local to the for loop.
It is good practice to always use braces for the body of a for loop (also if, else, ...etc), even if you would only have one
statement in the body.
dp[i][i] = 1; is also a bad assignment: it just is not true that integerPartition(i, i) always returns 1. It happens to be true
for small values of i, but not when i is greater than 3. For instance, integerPartition(4, 4) should return 5.
Just remove this line.
In the final nested for loop you are mixing up the row/column in your dp array. Note that you had reserved the first dimension for n and the second dimension for m, so opposite to the parameter order.
That is fine, but you do not stick to that decision in this for loop. Instead of dp[i][j-1] you should have written dp[i-1][j], and instead of dp[i-j][j] you should have
written dp[i][j-i]. And so the if condition should be adapted accordingly.
There is no return statement in your version, but maybe you just forgot to include it in the question. It should be
return dp[n][m];
Here is the corrected code:
long long int dp[n+1][m+1];
for(int i = 0; i <=n; i++) {
for(int j = 0; j <= m; j++) {
dp[i][j] = 0;
}
}
for (int i = 1; i <= n; i++) {
dp[i][0] = 1;
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m ; j++) {
dp[i][j] = dp[i-1][j];
if (j >= i) {
dp[i][j] += dp[i][j-i];
}
}
}
return dp[n][m];
Not sure that this technically is DP, but if your goal is to get the benefits of DP, memorization might be a better approach.
The idea is made up of 2 parts:
At the start of each call to integerPartition, look up in a table (your dp will do nicely) to see if that computation has already been done, and if it has, just return the value stored in the table.
Just before any point where integerPartition is to return a value, store it in the table.
Note that this means you don't need to try to "pivot" the original code -- it proceeds as it did originally, so you are almost guaranteed to get the same results, but without as much unnecessary re-computation (at the code of extra storage).
so, basis of your code comment,
I am going to assume you only want 1 when n > 0 and m = 0 according to your recursive code, but in dp code, you interchanged them, that is i go to upto n, and j go upto m
so updating your code, try to find the mistake
// n -> no. of persons
// m -> amount of money to be distributed
// dp table of order (n+1)*(m+1)
long long int dp[n+1][m+1] ;
//initializing values to 0
for(i = 0; i<=n ; i++)
for(j = 0; j<= m ; j++)
dp[i][j] = 0;
Print(n,m,dp);
cout << "\n";
//Case 1 - if there is no persons i.e n = 0 answer will be 0
//Case 2 - if there is no money i.e. m = 0 there is only 1 way answer will be 1
for ( i = 1; i<= n; i++){
dp[i][0] = 0;
}
for(int j = 1; j <= m; j++){
dp[0][j] = 1;
}
Print(n,m,dp);
for ( i = 1; i<= n ; i++){
for ( j = 1; j<= m ; j++){
dp[i][j] = dp[i][j-1] ;
if(i>=j){
dp[i][j] += dp[i-j][j];
}
// else if(i==j){
// dp[i][j] += 1;
// }
}
}
Given a array containing only 0 and 1 and a integer value k.
You should choose k digits at time and flip all of them. Find minimum cost for making all values same. If it is not possible then give -1.
This is a simple greedy problem. I am assuming you can't flip less than k digits any time.
Find minimum cost for making all values same.
To solve this, first we will try to make all values 1 and then we'll try to make all values 0. Between these, which will take minimum steps will be our answer.
Here is my pseudo-code. The pseudo-code is self-explanatory and that's why I am not adding explanation. I am giving code for making all values 1, hope you can do for both.
int cnt = 0;
for(int i = 0; i < arr.length() - k + 1; i++) {
if(arr[i] == '1') {
continue;
}
for(int j = 0; j < k; j++) {
arr[i + j] = (arr[i + j] == '0') ? '1' : '0';
}
cnt++;
}
bool flag = true;
for(int i = 0; i < arr.length(); i++) {
if(arr[i] == '0') {
flag = false;
break;
}
}
if(flag) {
print(cnt);
} else {
print("-1");
}
I have a couple of questions I couldn't find online regarding Shell sort with Shell's gap.
public static void shell(int[] a) {
int increment = a.length / 2;
while (increment > 0) {
for (int i = increment; i < a.length; i++) {
int j = i;
int temp = a[i];
while (j >= increment && a[j - increment] > temp) {
a[j] = a[j - increment];
j = j - increment;
}
a[j] = temp;
}
if (increment == 2) {
increment = 1;
} else {
increment *= (5.0 / 11);
}
}
}
This is the code I found online, but I don't really understand the last else statement. What does 5.0/11 represent?
Also I need to analyse the complexity of the algorithm, though I'm receiving pretty perplexing results:
It seems that it is O(n) either best and worst cases. Are these results legit?
5.0/11 is actually used to get the half of the increment. Anything <0.5 and >0.45 will work to obtain the half of the value in round figures.
I am trying to study for a test in my programming language concepts class.
I am trying to understand how to solve this problem. Our professor said we don't need to use formal notation to prove the problem as long as he can understand what we are saying.
I missed the lecture where he solved the problem and I'm having a very hard time finding resources to help me solve it on my own.
Would be so thankful for an explanation.
Problem
Use axiomatic semantics to prove that the postcondition is true following the execution of the program assuming the precondition is true
Precondition: n ≥ 0 and A contains n elements indexed from 0
bound = n;
while (bound > 0) {
t = 0;
for (i = 0; i < bound-1; i++) {
if (A[i] > A[i+1]) {
swap = A[i];
A[i] = A[i+1];
A[i+1] = swap;
t = i+1;
}
}
bound = t;
}
Postcondition: A[0] ≤ A[1] ≤ ...≤ A[n-1]
Lets number the lines for reference:
1. bound = n;
2. while (bound > 0) {
3. t = 0;
4. for (i = 0; i < bound-1; i++) {
5. if (A[i] > A[i+1]) {
6. swap = A[i];
7. A[i] = A[i+1];
8. A[i+1] = swap;
9. t = i+1;
10. }
11. }
12. bound = t;
13. }
Consider the following assertions:
Before entering 12
t < bound
Before entering 11
A[i] <= A[t] for all i such that 0 <= i < t
Before entering 13
A[k] <= A[j] for all indexes k and j such that bound <= k <= j <= n-1
After leaving 12
bound has decreased
Let's see now why the assertions are true
This is true because t=0 before the loop and if set inside the if it is
t = i + 1 < (bound - 1) + 1 = bound.
This is true because otherwise a swap would have happened.
This is true because of 2 and because the for doesn't change entries with indexes j from bound to n-1.
This is true because of 1.
From assertion 4 we deduce that the while loop, and so the algorithm, finishes in n steps at most, when bound = 0.
The postcondition now follows from assertion 3 for bound = 0.