So I have a program that I have created for finding an optimal binary search tree and it works great when the data set is around 100 but when I try and use a data set >1000 I get an access violation when weight[i][i] = frequency[i]; is called inside the computeOBST function. I'm not sure if that data set is to large or what. I'm stuck and not sure what else to try any help would be great.
int* keys = new int[numKeys];
int* keyLevel = new int[numKeys];
int* frequency = new int[numKeys];
int** weight = new int*[numKeys+2];
int** cost = new int*[numKeys];
int** root = new int*[numKeys];
void allocateArraySpace(int n){
int i;
// Allocate space for the 2-dim'l cost array
for (i = 0; i < numKeys + 2; i++) {
cost[i] = new int[numKeys + 2];
}
for (i = 0; i < numKeys + 1; i++) {
keyLevel[i] = numKeys + 1;
}
// Allocate space for the 2-dim'l root array
for (i = 0; i < numKeys + 1; i++) {
root[i] = new int[numKeys + 1];
}
//Allocate space for the 2-dim'l weight array
for (i = 0; i <= numKeys + 2; i++) {
weight[i] = new int[numKeys + 2];
}
}
void computeOBST(int n) {
numKeys = n;
int i, j, k, h, m;
allocateArraySpace(numKeys);
//creating weight matrix
for (int i = 1; i <= numKeys + 1; i++)
{
weight[i][i] = frequency[i];
for (j = i + 1; j <= numKeys; j++)
weight[i][j] = weight[i][j - 1] + frequency[j];
}
//
for (i = 1; i <= numKeys; i++)
for (j = i + 1; j <= numKeys + 1; j++)
cost[i][j] = INT_MAX;
//
for (i = 1; i <= numKeys + 1; i++)
cost[i][i - 1] = 0;
//
for (i = 1; i <= numKeys; i++) {
cost[i][i] = weight[i][i];
root[i][i] = i;
}
cost is only of size numKeys, but in your loop in allocateArraySpace you access numKeys+2 elements of it? There are similar issues for the other arrays.
Remember that arrays in C++ are 0-based, so if you do cost = new int *[numKeys], then cost[numKeys-1] is okay but cost[numKeys] and cost[numKeys+1] are out of bounds.
int* frequency = new int[numKeys]
then
for (int i = 1; i <= numKeys + 1; i++) { weight[i][i] = frequency[i]; ...
You will go out of bound. Undefined Behavior. It happens that this UB for small values does not result in a segmentation fault, while it does so for high values of numKeys.
This is just an example, you have the same error at many placrs. Check again all your loops and array bounds and set the correct limits.
In general, when you span an array of size numKeys, you scan it in the following way (remember C arrays are zero-based):
for (int i = 0; i < numKeys; i++) // first index is 0, last is numKeys-1
Related
void Counting_Sort(vector<int>& A)
{
const int size = A.size();
int max = A[0];
for (int i = 1; i < size; i++)
if (max > A[i])
max = A[i];
int* C = new int[max + 1]{ 0 };
for (int i = 0; i < max + 1; i++)
C[A[i]] = C[A[i]] + 1;
for (int i = 1; i < max + 1; i++)
C[i] = C[i] + C[i - 1];
int* B = new int[size];
for (int i = size-1; i >= 0; i--)
B[C[A[i]] - 1] = A[i]; // <-- Warning here
}
I'm not really sure why I get the warning or what exactly it means. Setting size-1 in for loop to size-2 removes the warning, but I don't uderstand why.
I notice four separate issues with your sample code:
The computation of maximum is incorrect. Your condition should be testing if (A[i] > max)
The Counting Sort algorithm's "accumulation step" should be iterating over the input data. That is, the loop should be the following (up to size, not up to max + 1):
for (int i = 0; i < size; i++)
C[A[i]] = C[A[i]] + 1;
The algorithm's final loop forgot to update the destination of each "Counting Sort bin". That is, the final loop should be the following:
for (int i = size - 1; i >= 0; i--) {
B[C[A[i]] - 1] = A[i];
C[A[i]] = C[A[i]] - 1;
}
Don't forget to use delete[] on B and C when you are done with them.
Here is the fully edited result:
#include <iostream>
#include <vector>
void Counting_Sort(std::vector<int>& A) {
const int size = A.size();
int max = A[0];
for (int i = 1; i < size; i++)
if (A[i] > max)
max = A[i];
int* C = new int[max + 1]{ 0 };
for (int i = 0; i < size; i++)
C[A[i]] = C[A[i]] + 1;
for (int i = 1; i < max + 1; i++)
C[i] = C[i] + C[i - 1];
int* B = new int[size];
for (int i = size-1; i >= 0; i--) {
B[C[A[i]] - 1] = A[i];
C[A[i]] = C[A[i]] - 1;
}
for (int i = 0; i < size; i++)
std::cout << "B[" << i << "] is " << B[i] << "\n";
delete[] B;
delete[] C;
}
int main() {
std::vector<int> A = {6, 1, 3, 3, 6, 9};
Counting_Sort(A);
return 0;
}
The compliler says that the size of B is 4xsize bytes long but in some cases, 8 bytes might be written, which might overpass the 4xsize bytes length.
Take the example of A = {10} for instance.
I am tasked with creating a function that takes in an array/vector of coins and a value to be reached. Rather than the function simply returning the minimum number of coins needed, the function must return an array/vector that essentially has the info of how many coins of each denomination should be used such that the least amount of coins are used.
For example, the array coins holds [1, 2, 5, 10] and the desired value is 12 cents. The function should take all of this in and return an array that has the following numbers in it: [0, 1, 0, 1], which denotes that 0 1-cent coins should be used, 1 2-cent coin should be used, 0 5-cent coins should be used, and 1 10-cent coin should be used.
I am using c++ and have to use a dynamic programming algorithm, which I am able to do to just return the minimum number of coins needed. But, I am not sure how to generate the right numbers to fill an array or vector to be returned.
This is what I currently have:
int *minCoins(int coins[], int size, int value)
{
int *table = new int[value + 1];
table[0] = 0;
for (int i = 1; i <= value; i++)
table[i] = INT_MAX;
for (int i = 1; i <= value; i++)
{
for (int j = 0; j < size; j++)
if (coins[j] <= i)
{
int sub_res = table[i - coins[j]];
if (sub_res != INT_MAX && sub_res + 1 < table[i])
table[i] = sub_res + 1;
}
}
//this is where I am unsure of what to do. should I return table or modify coins somehow?
}
Any help is appreciated!
Instead of storing just the minimum number of coins table[i] for a sum i in a knapsack, we can additionally store the last coin type last[i] that was used to get that table[i]. After that, we can do i -= coins[last[i]] in a loop to get all the coins, until i becomes zero.
In code:
int *minCoins(int coins[], int size, int value)
{
int *last = new int[value + 1]; // this line added
int *table = new int[value + 1];
table[0] = 0;
for (int i = 1; i <= value; i++)
table[i] = INT_MAX;
for (int i = 1; i <= value; i++)
{
for (int j = 0; j < size; j++)
if (coins[j] <= i)
{
int sub_res = table[i - coins[j]];
if (sub_res != INT_MAX && sub_res + 1 < table[i])
{
table[i] = sub_res + 1;
last[i] = j; // this line added
}
}
}
int *res = new int[size]; // this will be the answer
for (int i = 0; i < size; i++)
res[i] = 0;
int cur = value; // the value left
while (cur > 0)
{
res[last[cur]] += 1; // add the current coin
cur -= coins[last[cur]]; // proceed to the next coin
}
delete[] table;
delete[] last;
return res;
}
you can use pair< int, bool> dp[i][j] where i is the answer for 1 to i indexes with value j then if we use the i-th coin then dp[i][j].second = true else false then at the end when you reach the minimum answer you can use recursive function and for each dp[i][j] that you reach, if the bool is true you must go to dp[i - 1][j - a[i]] and add i to answer (a is value of coin) else you must go to dp[i - 1][j] without doing anything
dp update:
if(dp[i - 1][j].first < dp[i - 1][j - a[i]].first + 1)
{
dp[i][j].second = false;
dp[i][j].first = dp[i - 1][j].first;
}
else
{
dp[i][j].second = true;
dp[i][j].first = dp[i - 1][j - a[i]].first + 1;
}
recursive function:
void func(int i,int j)
{
if(i == -1)
return;
if(dp[i][j].second)
ans.push_back(i), func(i - 1,j - a[i]);
else
func(i - 1,j);
}
How do I solve following programming riddle in O(N)?
Array of integers: Tab[N]
Find max(Tab[K] - K + Tab[L] + L)
where 0 <= K <= L <= N
The only solution I can come up with is O(N^2) where I compare each element and update maximum sum.
int curr_max = INTEGER_MIN;
for(int i = 0; i < N; i++){
for(int j = i; j < N; j++){
curr_max = max(Tab[i]-i + Tab[j] + j,curr_max);
}
}
In general, a possible way to solve such kind of tasks, due to K<=L constraint, is to use pre-calculated running max. (The version below can be optimized, but anyway has O(N) time and space complexity.)
int t[N+1]; // input
int a[N+1]; // running max t[i]-i, left to right
a[0] = t[0]-0;
for (int i = 1; i <= N; ++i)
a[i] = max(a[i-1], t[i]-i);
int b[N+1]; // running max t[i]+i, right to left
b[N] = t[N]+N;
for (int i = N-1; i >= 0; --i)
b[i] = max(b[i+1], t[i]+i);
int mx = a[0] + b[0];
for (int i = 1; i <= N; ++i)
mx = max(mx, a[i] + b[i]);
However, in our case, it can be shown that if K: Tab[K]-K -> max and L: Tab[K]+K -> max then K<=L. In other words, if L and K are indices of the two maxima respectively, the property L<=K holds. Therefore, the naïve approach should work too:
int K = 0, L = 0;
for (int i = 1; i <= N; ++i) {
if (t[i]-i > t[K]-K)
K = i;
if (t[i]+i > t[L]+L)
L = i;
}
assert(K <= L);
int mx = t[K]-K + t[L]+L;
How about:
int L_max = INTEGER_MIN;
int K_max = INTEGER_MIN;
for(int i=0; i<N; i++)
{
K_max = max(Tab[i] -i, K_max);
L_max = max(Tab[i] +i, L_max);
}
curr_max = K_max + L_max;
Note that it does not validate K <= L, neither does the code in the question.
I found this problem somewhere in a contest and haven't been able to come up with a solution yet.
The boy has apples and keeps in boxes. In one box no more than N/2.
How many methods he can put candies to boxes.
So what I'm trying to do is to implement solution using DP. Here is my code:
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <unistd.h>
#include <vector>
#define size 1002
using namespace std;
long long a[size][size];
int n, k;
int main()
{
cin >> n >> k;
int kk = n/2;
for(int i = 0; i <= k; ++i)
a[0][i] = 1;
a[0][0] = 0;
for(int i = 0; i <= kk; ++i)
a[i][1] = 1;
for(int i = 1; i <= n; ++i) {
for(int j = 2; j <= k; ++j) {
int index = 0;
long long res = 0;
while(1) {
res += a[i-index][j - 1];
index += 1;
if(index == kk + 1 || i-index < 0)
break;
}
a[i][j] = res;
}
}
cout << a[n][k] << endl;
}
But the problem is that we have large numbers in input like:
2 ≤ N ≤ 1000 is a quantity of the candies, N - even; 2 ≤ S ≤ 1000 - is a quantity of small boxes.
So, for input like N = 1000 and S = 1000, I have to spent 5*10^8 operations. And the numbers are very big, so I have to use BigInteger arithmetics?
Maybe there is algorithm to implement the problem in linear time? Thanks and sorry for my English!
You can easily decrease the time complexity from O(kn^2) into O(nk) by the following observation:
for(int i = 1; i <= n; ++i) {
for(int j = 2; j <= k; ++j) {
int index = 0;
long long res = 0;
while(1) {
res += a[i-index][j - 1];
index += 1;
if(index == kk + 1 || i-index < 0)
break;
}
a[i][j] = res;
}
}
for each a[i][j], we can easily see that
a[i][j] = sum a[k][j - 1] with k from (i - n/2) to i
So, if we create an array sum to store the sum from all indexes of the previous step, we can reduce one for loop from the above nested loop
a[i][j] = sum[i] - sum[i - (n/2) - 1];
Pseudo code:
long long sum[n + 1];
for(int j = 2; j <= k; ++j) {
long long nxt[n + 1];
for(int i = 1; i <= n; ++i) {
int index = 0;
long long res = sum[i] - sum[i - (n/2) - 1];
a[i][j] = res;
nxt[i] = nxt[i - 1] + a[i][j];//Prepare the sum array for next step
}
sum = nxt;
}
Note: This above code is not handled the initialization step for array sum, as well as not handle the case when i < n/2. Those cases should be obvious to handle.
Update:
My below Java solution get accepted by using similar idea:
public static void main(String[] args) throws FileNotFoundException {
// PrintWriter out = new PrintWriter(new FileOutputStream(new File(
// "output.txt")));
PrintWriter out = new PrintWriter(System.out);
Scanner in = new Scanner();
int n = in.nextInt();
int s = in.nextInt();
BigInteger[][] dp = new BigInteger[n + 1][2];
BigInteger[][] count = new BigInteger[2][n + 1];
int cur = 1;
for (int i = 0; i <= n / 2; i++) {
dp[i][0] = BigInteger.ONE;
count[0][i] = (i > 0 ? count[0][i - 1] : BigInteger.ZERO)
.add(dp[i][0]);
}
for (int i = n / 2 + 1; i <= n; i++) {
dp[i][0] = BigInteger.ZERO;
count[0][i] = count[0][i - 1];
}
for (int i = 2; i <= s; i++) {
for (int j = 0; j <= n; j++) {
dp[j][cur] = dp[j][1 - cur].add((j > 0 ? count[1 - cur][j - 1]
: BigInteger.ZERO)
.subtract(j > n / 2 ? count[1 - cur][j - (n / 2) - 1]
: BigInteger.ZERO));
count[cur][j] = (j > 0 ? count[cur][j - 1] : BigInteger.ZERO)
.add(dp[j][cur]);
}
cur = 1 - cur;
}
out.println(dp[n][1 - cur]);
out.close();
}
How can I store a 1D array of 9 into a 2D array of 3x3? This is my current attempt:
for (j = 0; j < 3; j++)
{
if (i = 0)
{
a[i][j] = (int)data1[j];
}
if (i = 1)
{
a[i][j] = (int)data1[j + 3];
}
if (i = 2)
{
a[i][j] = (int)data1[j + 6];
}
}
}
something like this:
for (int i = 0; i < 9; i++)
{
a[i / 3][i % 3] = data[i];
}
And as ThisHandleNotInUse pointed out, MAYBE this one is more optimized depending on the circumstances and still scales to larger arrays with minor tweaking.
for (int i = 0; i < 9; i += 3)
{
for (int j = 0; j < 3; j++)
{
a[i][j] = data[i + j];
}
}
First of all. Logical equal sign must be written like this:if (i == 0)
This will check condition.
if (i=0)
Is not correct because you do assignement operator for i
You can try this:
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
if(i == 0)
{
a[i][j] = (int)data1[j];
}
if (i == 1)
{
a[i][j] = (int)data1[j+3];
}
if (i == 2)
{
a[i][j] = (int)data1[j+6];
}
}
}
If you are coding in c++, if(I=2) is incorrect it should be if (I==2) and I'm not sure why you need that
One possible solution is to have two nested for loops as you already have and this code: a[i][j]=data[j*3+i]. No if is needed then.
How optimized do you need this to be? What does your array contain? If your array contains structs, you're going to be copying them no matter what you do. If it contains references, you're going to be copying them (the references) no matter what you do.
If I were regularly converting an array[9] to an array[3,3], I'd just do this:
(arr = Old Array)
Array[,] NewArr = new Array[,]{ { arr[0], arr[1], arr[2] }, {arr[3], arr[4], arr[5]}, {arr[6], arr[7], arr[8]} };
EDIT: commenter below pointed out you were using a jagged array and not a multidimensional one in which case, in C#, the syntax would be:
Array[][] NewArr = new Array[][]{ new Array[]{ arr[0], arr[1], arr[2] }, new Array[]{ arr[3], arr[4], arr[5]}, new Array[]{ arr[6], arr[7], arr[8] } };