Redefining operators c++ - c++

I tried to redefine + operator which was to sum 2 matrices and return the summation matrice in c++. But somehow it displays 0 all the time. What I'm missing? Here is my code.
Also I've written this code.
#include <iostream>
using namespace std;
class matrix{
public:
int a[100][100], n;
matrix(int b[100][100], int n){
for(int i=0; i<n; i++){
for(int l=0; l<n; l++){
a[i][l]=b[i][l];
}
}
n=n;
}
matrix(){}
void matrix_input(int n){
for(int i=0; i<n; i++){
for(int l=0; l<n; l++){
cin >> a[i][l];
}
}
}
void matrix_print(int n){
for(int i=0; i<n; i++){
for(int l=0; l<n; l++){
cout << a[i][l] << " ";
}
cout << endl;
}
}
} ;
matrix operator + (matrix x, matrix y){
int s;
int n=x.n;
matrix sum;
for(int i=0; i<n; i++){
for(int l=0; l<n; l++){
sum.a[i][l]=y.a[i][l]+x.a[i][l];
}
}
return sum;
}
int main(){
int n;
cin >> n;
matrix o;
o.matrix_input(n);
matrix c;
c.matrix_input(n);
matrix sum;
sum=o+c;
sum.matrix_print(n);
return 0;
}

In your matrix constructor, n = n assigns the parameter to itself. You probably meant this->n = n;. However, it would be better for you to use the member-initialiser list:
matrix(int b[100][100], int n) : n(n)
{
for(int i=0; i<n; i++) {
for(int l=0; l<n; l++) {
a[i][l]=b[i][l];
}
}
}
And your operator + does not set sum.n.
UPDATE
matrix_input() does not modify the matrix's n member either. In other words, your class does not maintain its own invariants. Querying x.n inside operator + is then meaningless.
You should modify matrix so that its member n is always valid and reflects what's in the matrix. You can then drop the parameter n from matrix_print().
And BTW, why do you call your member functions matrix_something? They are already in the scope of matrix. Just input and print would be fine.

Your main error is in the line n=n, which is a self-assignment.
As you can guess this is pretty much a no-op when n is an integer (and should be most of the time). You mean this->n = n;
(better way is to not clash the naming but that small fix will work. You also need to fix operator+ to assign sum.n = n;
The local n parameter takes precedence over the class member so you need this->n to qualify the class member.
Incidentally your matrices are quite large (10,000 ints) so are expensive to copy. So your operator+ overload would be more efficient if it took its parameters as const references.
Presumably n is a logical size, as physically your matrix is always 100 * 100. Your default constructor though should at least initialize n to 0 or subsequent behaviour trying to read this matrix would be undefined. You should possibly put in assertion checks when reading what might be beyond the bounds of your matrices. (Your operator+ could check that both have the same dimension).
If you want to use "dynamic" sizing, so you only use the memory resources you are going to actually use for your matrix, you would implement it a bit differently. I guess that would be a more advanced exercise for your level.
Incidentally it "printing 0 all the time" is random as the behaviour you should get is actually undefined, as x.n (and sum.n in the addition) is an uninitialised variable that you are then reading.

Related

2-D vector Size

In C++ , I Made A Code That has A 2D Vector in it and Users are Required to give The inputs In 2D vector . I find It difficult To find The no. of rows in 2 vector with the help of size function.
#include <bits/stdc++.h>
#include <vector>
using namespace std;
int diagonalDifference(vector<vector<int>> arr)
{
int d = arr[0].size();
cout << d;
return 0;
}
int main()
{
int size;
cin >> size;
vector<vector<int>> d;
for (int i = 0; i < size; i++)
{
d[i].resize(size);
for (int j = 0; j < size; j++)
{
cin >> d[i][j];
}
}
cout << diagonalDifference(d);
}
The Output Should BE No. Rows , But it is coming NULL
Here
vector<vector<int>> d;
for (int i = 0; i < size; i++)
{
d[i].resize(size);
//...
d is a vector of size 0 and accessing d[i] is out of bounds. You seem to be aware that you first have to resize the inner vectors, but you missed to do the same for the outer one. I dont really understand how your code can run as far as printing anything for arr[0].size(); without segfaulting. Anyhow, the problem is that there is no element at arr[0].
But first, Look at your function argument -> is a copy of your vector ,use (vector<> & my vec) to avoid the copying mechanism of vector class (copy constructor for instance) cause if you put there your vector as a parameter and u will make some changes inside the function brackets you will not see any results ( if you dont wanna change your primary vector from function main, keep it without changes).
Secondly, look at code snippet pasted below.
std::vector<std::vector<typename>> my_vector{};
my_vector.resize(width);
for (size_t i = 0; i < my_vector.size(); ++i)
{
my_vector[i].resize(height);
}
It gives you two dimensional vector
Operator[] for vector is overloaded and you have to use my_vector[0].size() just
my_vector[1].size() and so on ! I recommend for that displaying the size by kind of loops given in c++ standards
Regards!

Problems with for loop c++

i used to code in javascript, but my new school force me to learn c++.
Im kind new in this language, and here's the problem:
In javascript i can write such a code:
for(let i = 0; i < 10; i++){
var variable[i] = i+3;
}
for(let j = 0; j < 10; j++){
console.log(variable[j]);
}
You may say 'Why don't you just write the code into 1 for loop', but that's only example.
And now i'm trying to rewrite above code to cpp:
int n,k,w;
cin>>n>>k;
for(int i = 0; i < n; i++){
int w[i];
cin>>w[i];
}
//some code here
for(int i = 0; i < n; i++){
cout<<w[i];
}
And here's the question. How can i cout all variables w with index i, cause im getting an error [Error] invalid types 'int[int]' for array subscript.
What you probably want is:
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec;
int size = 0;
std::cin >> size;
for(int i = 0; i < size; i++){
int number = 0;
std::cin >> number;
vec.push_back(number);
}
for(int i : vec){
std::cout << i << " ";
}
}
std::vector<int> is a class designed to provide an interface to resizable array. The push_back() function appends the vector with given argument.
The last loop, which is called a ranged-based for(), is used to print all elements of the vector. You can replace it with plain old for() loop with indexing, since std::vector supports operator [], but if ranged-based approach is sufficient, it should be preferred.
EDIT: I don't know JavaScript, but I assume (from your example) that variables declared inside loops are visible everywhere. This is not the case in C++. Variables' visibility is dependent on the scope they are declared in. If you want your list/array/vector/any other container to be visible to those two for() loops, you have to declare it outside them - like in my example above.
EDIT2: While you should almost always use std::vector for such tasks, one could argue that they want to disable resizing the container. In this case, we are left with simple dynamic allocation. We reach for <memory> library, since we shouldn't manage it ourselves:
#include <iostream>
#include <memory>
int main() {
int size = 0;
std::cin >> size;
auto arr = std::make_unique<int[]>(size);
for(int i = 0; i < size; i++){
int number = 0;
std::cin >> number;
arr[i] = number;
}
for(int i = 0; i < size; i++){
std::cout << arr[i] << " ";
}
}
For auto, either read here or imagine that it's just a magic type that is (almost always) correct. It's like var in Python or JavaScript (but later on its type cannot be changed).
For std::unique_ptr<T[]>, either read here or imagine that it's just a dynamically allocated array that automatically delete[]s itself. If you did not learn about dynamic allocation yet, simply ignore what that means and wait until it's introduced.
Notice that we also got rid of the ranged-based for() loop. Unfortunately, it does not work with plain, dynamically allocated arrays.
Not all compilers support VLA so stick to the Standards; always specify a constant size for arrays. If you need some dynamically changed size then consider using another type of containers like: std::vector.
Also why you re-declared int w inside the for loop? It is local to for loop and changes to it won't affect the outer one.
You get a compile time error in the second loop that complains that w is not an array. To solve it make int w[] outer and on top of the two loops.
int n, k;
cin >> n >> k;
int w[n];
for(int i = 0; i < n; i++)
cin >> w[i];
//some code here
for(int i = 0; i < n; i++)
cout << w[i];
The alternative to VAL use std::vector:
std::vector<int> w;
int n, k;
std::cin >> n;
for(int i(0); i!= n; ++i){
std::cin >> k;
w.push_back(k);
}
for(auto i(0); i != w.length(); ++i)
std::cout << w[i] << ", ";

How to efficiently find coefficients of a polynomial from its roots? [duplicate]

This question already has answers here:
Sum of multiplication of all combination of m element from an array of n elements
(3 answers)
Closed 7 years ago.
Given are the n roots of a polynomial whose leading coefficient is 1.
How do I efficiently find out the coefficients of this polynomial?
Mathematically,
I know that if the first coefficient is 1, then sum of product roots taken k at a time will be the k+1-th coefficient of the polynomial.
My code is based on this approach.
In other words, how to optimally find the sum of product of numbers from a list taken k at a time.
int main()
{
int n, sum;
cin >> n;
int a[n];
for (int i=0; i<n; i++) cin >> a[i];
//for the second coefficient
sum=0;
for (int i=0; i<n; i++)
{
sum+=a[i];
}
cout << sum << endl;
//for the third coefficient
sum=0;
for (int i=0; i<n; i++)
{
for (int j=i+1; j<n; j++)
{
sum+=a[i]*a[j];
}
}
cout << sum << endl;
}
I have thought of marking the numbers on whether I have taken them into the product or not for the purpose of higher coefficients, but have not written the code for it as it is practically of no use if the degree of polynomial is large.
You need to compute the product of linear factors
(x-z1)·(x-z2)·…·(x-zn)
This can be implemented inductively by repeatedly multiplying a polynomial with a linear factor
(a[0]+a[1]·x+…+a[m-1]·x^(m-1))·(x-zm)
= (-a[0]·zm) + (a[0]-a[1]·zm)·x + … + (a[m-2]-a[m-1]·zm) ·x^(m-1) + a[m-1]·x^m
In place this can be implemented as loop
a[m] = a[m-1]
for k = m-1 downto 1
a[k] = a[k-1] - a[k]*zm
end
a[0] = -a[0]*zm
This gives a total of n²/2 multiplications and a like number of subtractions for the multiplication of all n linear factors.
First of all in C++ a[n] is a static array, so compiler need to know n during compile time, which is not the case here. So the code is "not correct" in C++. I know it will compile in gcc or other compilers, but it is against C++ standard. See C++ declare an array based on a non-constant variable? What you need here is a dynamic array, using new and delete command, or you can use more safe std::vector class from STL.
Now, the main problem here is that you need k nested loops, if you want to calculate k'th coefficients, (I am assuming 1 is 0th coefficient, not 1st, just convention). So, you need to implement variable no. of nested for loops in your code. I am posting the solution of your problem, in which I used a method to implement variable no. of nested for loops. Hope this will solve your problem.
#include <iostream>
#include <cmath>
#include <vector> // include vector class
using namespace std;
double coeff(int,const vector<double>& ); // function declaration to to calculate coefficients
int main()
{
int N = 5; // no. of roots
// dynamic vector containing values of roots
vector<double> Roots(N);
for(int i = 0 ; i<N ; ++i)
Roots[i] = (double)(i+1); // just an example, you can use std::cin
int K = 2; // say you want to know K th coefficient of the polynomial
double K_th_coeff = coeff(K,Roots); // function call
cout<<K_th_coeff<<endl; // print the value
return 0;
}
double coeff(int k,const vector<double>& roots)
{
int size = roots.size(); // total no. of roots
int loop_no = k; // total no. of nested loops
vector<int> loop_counter(loop_no+1); // loop_counter's are the actual iterators through the nested loops
// like i_1, i_2, i_3 etc., loop_counter[loop_no] is needed to maintain the condition of the loops
for(int i=0; i<loop_no+1; ++i)
loop_counter[i]=0; // initialize all iterators to zero
vector<int> MAX(loop_no+1); // MAX value for a loop, like for(int i_1=0; i_1 < MAX[1]; i++)...
for(int i=0 ; i<loop_no ; ++i)
MAX[i] = size - loop_no + i + 1; // calculated from the algorithm
MAX[loop_no]=2; // do'es no matter, just != 1
int p1=0; // required to maintain the condition of the loops
double sum(0); // sum of all products
while(loop_counter[loop_no]==0)
{
// variable nested loops starts here
int counter(0);
// check that i_1 < i_2 < i_3 ....
for(int i = 1 ; i < loop_no; ++i)
{
if(loop_counter[i-1] < loop_counter[i])
++counter;
}
if(counter == loop_no - 1) // true if i_1 < i_2 < i_3 ....
{
double prod(1);
for(int i = 0 ; i < loop_no ; ++i)
prod *= roots[loop_counter[i]]; // taking products
sum += prod; // increament
}
// variable nested loops ends here...
++loop_counter[0];
while(loop_counter[p1]==MAX[p1])
{
loop_counter[p1]=0;
loop_counter[++p1]++;
if(loop_counter[p1]!=MAX[p1])
p1=0;
}
}
return pow(-1.0,k)*sum; // DO NOT FORGET THE NEGATIVE SIGN
}
I have checked the code, and it is working perfectly. If you want to know how to implement variable no.of nested for loops, just visit variable nested for loops and see BugMeNot2013's answer.

C++ how to modify a 2D vector of objects size in a function initialized in the constructor?

Since I'm Italian, the function names are in Italian but really simple to understand: immagine=image, inserisci=insert, altezza=height, larghezza=width,mosaico =mosaic, righe=rows, colonne=columns.
So this program has 2 classes: an image with its attributes and a mosaic, which contains n images and this is represented through a 2D vector of obj Image (Immagine). The 2D vector has to be initialized in the constructor with r rows and c columns and using the inserisci (insert/add) function will then grow its dimension. Then if the element passed in the insert function has more rows/columns the insert function has to add the needed rows and columns in order to insert the element.
The problem is that even though I used pointers/references, every time I try to insert an element with a size that is bigger than the one initialized in the constructor, it gives me an error, meaning that the 2D vector that I modify in the insert function is not really edited... (look at the main when I insert: m2.inserisci(i4, 4, 4, &m2.immagini) since 4 rows > inital size of rows and same for columns gives me a runnning error..) Hope it is clear. This is my code:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
class Immagine{
private:
string nome;
public:
int altezza;
int larghezza;
Immagine(string,int,int);
string toString();
};
Immagine::Immagine(string n, int a, int l){
nome = n;
altezza = a;
larghezza= l;
}
string Immagine::toString(){
return nome;
}
class Mosaico{
public:
Mosaico(int, int,Immagine,vector< vector<Immagine> >*);
int getRighe();
int getColonne();
string getImmagine(int,int);
bool exist(int, int);
Immagine getIm(int,int);
void inserisci(Immagine,int,int,vector< vector<Immagine> >*);
vector< vector<Immagine> > immagini;
vector< vector<Immagine> >* aPointer= &immagini;
};
Mosaico::Mosaico(int r, int c,Immagine imm, vector< vector<Immagine> >* immag ){
(*immag).resize(r);
for(int i=0; i<(*immag).size(); i++)
for(int j=0; j<c; j++)
(*immag)[i].insert((*immag)[i].begin()+j,imm);
}
bool Mosaico::exist(int r, int c){
for(int i = 0; i < getRighe(); i++){
for(int j=0; j<getColonne(); j++){
if(i==r && j==c && immagini[r][c].toString()!= " "){
return true;
}
}
}
return false;
}
int Mosaico::getRighe(){
return immagini.size();
}
int Mosaico::getColonne(){
return immagini[1].size();
}
string Mosaico::getImmagine(int r, int c){
if(exist(r,c))
return immagini[r][c].toString();
}
Immagine Mosaico::getIm(int r, int c){
return immagini[r][c];
}
void Mosaico::inserisci(Immagine imm,int r, int c, vector< vector<Immagine> >* immag){
if(r<(*immag).size() && c<(*immag)[0].size()){
(*immag)[r][c]=imm;
}
else if(r>=(*immag).size() && c>=(*immag)[0].size()){
(*immag).resize(r);
for(int i=0; i<r; i++){
for(int j=(*immag)[0].size(); j<c; j++){
(*immag)[i].insert((*immag)[i].begin()+j, imm);
}
}
(*immag)[r][c]=imm;
}
else if(r>=(*immag).size() && c<(*immag)[0].size()){
(*immag).resize(r);
(*immag)[r][c]=imm;
}
else if(r<(*immag).size() && c>=(*immag)[0].size()){
for(int i=0; i<(*immag).size(); i++){
for(int j=(*immag)[0].size(); j<c; j++){
(*immag)[i].insert((*immag)[i].begin()+j, imm);
}
}
(*immag)[r][c]=imm;
}
}
int main() {
Immagine i1 ("I01",300,200);
Immagine i2 ("I02",300,400);
Immagine i3 ("I03",400,200);
Immagine i4 ("I04",400,400);
cout << "Creo un mosaico 2x2 con quattro immagini" <<endl;
Mosaico m2(2,2,i1,&m2.immagini) ;
cout<<m2.getRighe()<<endl;
cout<<m2.getColonne()<<endl;
for (int i=0; i < m2.getRighe(); i++) {
for (int j=0; j < m2.getColonne(); j++){
//if(m1.exist(i,j))
cout<<m2.getImmagine(i,j);
}
cout<<endl;
}
m2.inserisci(i1, 0, 0, &m2.immagini);
m2.inserisci(i2, 0, 1, &m2.immagini);
m2.inserisci(i3, 1, 0, &m2.immagini);
m2.inserisci(i4, 4, 4, &m2.immagini); //HERE IS WHERE I GET THE ERROR
cout <<"Stampa mosaico: "<<endl;
for (int i=0; i < m2.getRighe(); i++) {
for (int j=0; j < m2.getColonne(); j++){
cout<<m2.getImmagine(i,j);
}
cout<<endl;
}
}
By the way, this was a Java exercise and I tried to do it in C++. Thanks in advance!
Before I'll get to the details of the issues, let me first state that there are a lot of things in the code I'd do differently. Most prominently, I'd probably use a flat vector<Image> for storage instead of a vector<vector<..>>. But such things are better suited for CodeReview in my opinion (once the code is working).
The biggest problems in the OP's code are within the implementation of the inserisci function:
void Mosaico::inserisci(Immagine imm,int r, int c,
vector< vector<Immagine> >* immag) {
if(r < (*immag).size() && c < (*immag)[0].size()){
(*immag)[r][c]=imm;
}
This part is fine, if we assume that (*immag)[i].size() is the same for all i in [0, (*immag).size()). Let us call this assumption A. The [x, y) notation stands for a half-open-on-right interval (x is within that interval, y is not). Note that you can replace (*e).m with e->m, which I'll do in the following.
The assumption A is a class invariant: after every member function (except for the destructor), this class invariant must hold. Continuing with the inserisci function:
else if(r>=(*immag).size() && c>=(*immag)[0].size()){
(*immag).resize(r);
The *immag vector now has r elements. This is insufficient if you want to access the rth element, since indexing starts with 0. You need to have at least r+1 elements. Replace the above resize with:
int newRowCount = r+1;
(*immag).resize(newRowCount);
Continuing with the OP's function:
for(int i=0; i<r; i++){
This has the same off-by-one bug: replace r with newRowCount, or simply immag->size().
for(int i=0; i<immag->size(); i++){
Continuing with the OP's function:
for(int j=(*immag)[0].size(); j<c; j++){
(*immag)[i].insert((*immag)[i].begin()+j, imm);
}
}
With the above resize, we have added newRowCount - immag->size() new elements to the immag vector. Those new elements are vectors of the size 0. To be able to access the cth element of such a vector, we need to add at least c+1 elements to it.
The value of (*immag)[0].size() however changes after the first iteration of the outer loop such that (*immag)[0].size() == c for the remaining (*immag)[i] elements where i is in [1, newRowCount). This code won't add any new columns to those rows. A simple fix is:
int newColumnCount = c+1;
for(int j=(*immag)[i].size(); j < newColumnCount; j++){
(*immag)[i].insert((*immag)[i].begin()+j, imm);
}
}
(*immag)[r][c]=imm;
}
A note related to code review: You can very easily resize the inner elements as well, using the resize-overload which takes an additional argument:
(*immag)[i].resize(newColumnCount, imm);
Continuing with the OP:
else if(r>=(*immag).size() && c<(*immag)[0].size()){
(*immag).resize(r);
This suffers from the same off-by-one bug again. You need to have at least r+1 elements to access the rth element in the following
(*immag)[r][c]=imm;
}
And in the following piece of code, the same issues appear as in the second branch (that is, (*immag)[0].size() instead of referring to the current element's size, and j < c instead of j < newColumnCount).
else if(r<(*immag).size() && c>=(*immag)[0].size()){
for(int i=0; i<(*immag).size(); i++){
for(int j=(*immag)[0].size(); j<c; j++){
(*immag)[i].insert((*immag)[i].begin()+j, imm);
}
}
(*immag)[r][c]=imm;
}
}

Add OpenMP to program to calculate the determinant of an n x n matrix n x n

Here is code to find determinant of matrix n x n.
#include <iostream>
using namespace std;
int determinant(int *matrix[], int size);
void ijMinor(int *matrix[], int *minorMatrix[], int size, int row, int column);
int main()
{
int size;
cout << "What is the size of the matrix for which you want to find the determinant?:\t";
cin >> size;
int **matrix;
matrix = new int*[size];
for (int i = 0 ; i < size ; i++)
matrix[i] = new int[size];
cout << "\nEnter the values of the matrix seperated by spaces:\n\n";
for(int i = 0; i < size; i++)
for(int j = 0; j < size; j++)
cin >> matrix[i][j];
cout << "\nThe determinant of the matrix is:\t" << determinant(matrix, size) << endl;
return 0;
}
int determinant(int *matrix[], int size){
if(size==1)return matrix[0][0];
else{
int result=0, sign=-1;
for(int j = 0; j < size; j++){
int **minorMatrix;
minorMatrix = new int*[size-1];
for (int k = 0 ; k < size-1 ; k++)
minorMatrix[k] = new int[size-1];
ijMinor(matrix, minorMatrix, size, 0, j);
sign*=-1;
result+=sign*matrix[0][j]*determinant(minorMatrix, size-1);
for(int i = 0; i < size-1; i++){
delete minorMatrix[i];
}
}
return result;
}
}
void ijMinor(int *matrix[], int *minorMatrix[], int size, int row, int column){
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
if(i < row){
if(j < column)minorMatrix[i][j] = matrix[i][j];
else if(j == column)continue;
else minorMatrix[i][j-1] = matrix[i][j];
}
else if(i == row)continue;
else{
if(j < column)minorMatrix[i-1][j] = matrix[i][j];
else if(j == column)continue;
else minorMatrix[i-1][j-1] = matrix[i][j];
}
}
}
}
After adding OpenMP pragmas, I've changed the determinant function and now it looks like this:
int determinant(int *matrix[], int size){
if(size==1)return matrix[0][0];
else{
int result=0, sign=-1;
#pragma omp parallel for default(none) shared(size,matrix,sign) private(j,k) reduction(+ : result)
for(int j = 0; j < size; j++){
int **minorMatrix;
minorMatrix = new int*[size-1];
for (int k = 0 ; k < size-1 ; k++)
minorMatrix[k] = new int[size-1];
ijMinor(matrix, minorMatrix, size, 0, j);
sign*=-1;
result+=sign*matrix[0][j]*determinant(minorMatrix, size-1);
for(int i = 0; i < size-1; i++){
delete minorMatrix[i];
}
}
return result;
delete [] matrix;
}
}
My problem is that the result is every time different. Sometimes it gives correct value, but most often it is wrong. I think it's because of the sign variable. I am following the formula:
As you can see, in every iteration of my for loop there should be different sign but when I use OpenMP, something is wrong. How can I make this program to run with OpenMP?
Finally, my second issue is that using OpenMP does not make the program run quicker than without OpenMP. I also tried to make a 100,000 x 100,000 matrix, but my program reports an error about allocating memory. How can I run this program with very large matrices?
Your issues as I see it are as follows:
1) As noted by Hristo, your threads are stomping over each other's data with respect to the sign variable. It should be private to each thread so that they have full read/write access to it without having to worry about race conditions. Then, you simply need an algorithm to compute whether sign is plus or minus 1 depending on the iteration j independently from the other iterations. With a little thinking, you'll see that Hristo's suggestion is correct: sign = (j % 2) ? -1 : 1; should do the trick.
2) Your determinant() function is recursive. As is, that means that every iteration of the loop, after forming your minors, you then call your function again on that minor. Therefore, a single thread is going to be performing its iteration, enter the recursive function, and then try to split itself up into nthreads more threads. You can see now how you are oversubscribing your system by launching many more threads than you physically have cores. Two easy solutions:
Call your original serial function from within the omp parallel code. This is the fastest way to do it because this would avoid any OpenMP-startup overhead.
Turn off nested parallelism by calling omp_set_nested(0); before your first call to determinant().
Add an if clause to your parallel for directive: if(omp_in_parallel())
3) Your memory issues are because every iteration of your recursion, you are allocating more memory. If you fix problem #2, then you should be using comparable amounts of memory in the serial case as the parallel case. That being said, it would be much better to allocate all the memory you want before entering your algorithm. Allocating large chunks of memory (and then freeing it!), especially in parallel, is a terrible bottleneck in your code.
Compute the amount of memory you would need (on paper) before entering the first loop and allocate it all at once. I would also strongly suggest you consider allocating your memory contiguously (aka in 1D) to take better advantage of caching as well. Remember that each thread should have its own separate area to work with. Then, change your function to:
int determinant(int *matrix, int *startOfMyWorkspace, int size).
Instead of allocating a new (size-1)x(size-1) matrix inside of your loop, you would simply utilize the next (size-1)*(size-1) integers of your workspace, update what startOfMyWorkspace would be for the next recursive call, and continue along.