Given a n × n matrix, check whether the matrix is a Magic Square or not. A Magic Square is a matrix containing distinct elements from 1 to n * n such that the sum of every row, every column, and both diagonals is the same.
[Naive Approach] Using Diagonal and Row-Column Sum Verification - O(n * n) Time and O(n * n) Space
Use a boolean array to track visited items for uniqueness (all numbers from 1 to n*n should appear once)
Compute sum of first row (let us call this sum as target) so that we can match it later with every row, column and diagonal
Traverse the matrix and compute row and column sums and compare with the target. If not same, then return false. Also check if a visited item appears again, then return false.
Traverse both diagonals and compare the sums with the target sum.
C++
#include<iostream>#include<vector>usingnamespacestd;boolmagicSquare(vector<vector<int>>&mat){intn=mat.size();inttarget=0;// first row sumfor(intj=0;j<n;j++)target+=mat[0][j];// track uniquenessvector<int>visited(n*n+1,0);for(inti=0;i<n;i++){introwSum=0,colSum=0;for(intj=0;j<n;j++){rowSum+=mat[i][j];colSum+=mat[j][i];intval=mat[i][j];// range + duplicate checkif(val<1||val>n*n||visited[val])returnfalse;visited[val]=1;}if(rowSum!=target||colSum!=target)returnfalse;}intd1=0,d2=0;// diagonalsfor(inti=0;i<n;i++){d1+=mat[i][i];d2+=mat[i][n-i-1];}returnd1==target&&d2==target;}intmain(){vector<vector<int>>mat={{2,7,6},{9,5,1},{4,3,8}};cout<<(magicSquare(mat)?"true":"false");return0;}
Java
publicclassGFG{publicstaticbooleanmagicSquare(int[][]mat){intn=mat.length;inttarget=0;// Compute target sum (first row)for(intj=0;j<n;j++)target+=mat[0][j];// track valuesint[]visited=newint[n*n+1];for(inti=0;i<n;i++){introwSum=0,colSum=0;for(intj=0;j<n;j++){rowSum+=mat[i][j];colSum+=mat[j][i];intval=mat[i][j];// check range + duplicateif(val<1||val>n*n||visited[val]==1)returnfalse;visited[val]=1;}// validate row & columnif(rowSum!=target||colSum!=target)returnfalse;}intd1=0,d2=0;// diagonal sumsfor(inti=0;i<n;i++){d1+=mat[i][i];d2+=mat[i][n-i-1];}returnd1==target&&d2==target;}publicstaticvoidmain(String[]args){int[][]mat={{2,7,6},{9,5,1},{4,3,8}};System.out.println(magicSquare(mat)?"true":"false");}}
Python
defmagicSquare(mat):n=len(mat)# first row sumtarget=sum(mat[0])# track valuesvisited=[0]*(n*n+1)foriinrange(n):row_sum=0col_sum=0forjinrange(n):row_sum+=mat[i][j]col_sum+=mat[j][i]val=mat[i][j]# check range and duplicateifval<1orval>n*norvisited[val]:returnFalsevisited[val]=1# validate row & columnifrow_sum!=targetorcol_sum!=target:returnFalse# diagonal sumsd1=sum(mat[i][i]foriinrange(n))d2=sum(mat[i][n-i-1]foriinrange(n))returnd1==targetandd2==target# Driver Codeif__name__=="__main__":mat=[[2,7,6],[9,5,1],[4,3,8]]print("true"ifmagicSquare(mat)else"false")
C#
usingSystem;classGFG{staticboolmagicSquare(int[][]mat){intn=mat.Length;inttarget=0;// Sum of first rowfor(intj=0;j<n;j++)target+=mat[0][j];int[]visited=newint[n*n+1];for(inti=0;i<n;i++){introwSum=0;intcolSum=0;for(intj=0;j<n;j++){rowSum+=mat[i][j];colSum+=mat[j][i];intval=mat[i][j];// Check range and duplicatesif(val<1||val>n*n||visited[val]==1)returnfalse;visited[val]=1;}// Check row and column sumsif(rowSum!=target||colSum!=target)returnfalse;}intd1=0,d2=0;// Check diagonalsfor(inti=0;i<n;i++){d1+=mat[i][i];d2+=mat[i][n-i-1];}returnd1==target&&d2==target;}staticvoidMain(){int[][]mat={newint[]{2,7,6},newint[]{9,5,1},newint[]{4,3,8}};Console.WriteLine(magicSquare(mat)?"true":"false");}}
JavaScript
functionmagicSquare(mat){letn=mat.length;// first row sumlettarget=mat[0].reduce((a,b)=>a+b,0);// track valuesletvisited=newArray(n*n+1).fill(0);for(leti=0;i<n;i++){letrowSum=0,colSum=0;for(letj=0;j<n;j++){rowSum+=mat[i][j];colSum+=mat[j][i];letval=mat[i][j];// check range and duplicateif(val<1||val>n*n||visited[val])returnfalse;visited[val]=1;}// validate row & columnif(rowSum!==target||colSum!==target)returnfalse;}letd1=0,d2=0;// diagonal sumsfor(leti=0;i<n;i++){d1+=mat[i][i];d2+=mat[i][n-i-1];}returnd1===target&&d2===target;}// Driver Codeletmat=[[2,7,6],[9,5,1],[4,3,8]];console.log(magicSquare(mat)?"true":"false");
Output
true
[Expected Approach] Using a Single Pass - O(n * n) Time and O(n * n) Space
This is mainly an optimization over the above approach. Instead of doing one more iteration for diagonals, we update diagonal sums during traversal when i == j and i + j == n - 1 . Note that all main diagonal elements have i == j and all other diagonal elements have i + j == n-1. One more optimization we make is, we can compute the target as n * (n*n + 1) / 2. For a magic square.
How does the sum formula work? Sum of all numbers is 1 + 2 + 3, ... n2 which is equal to n2 × (n2 + 1)/2 [We have simply applied natural number sum formula for n = n2]. Now a magic square contains n divisions of the target sum (row wise or column wise sum), so we can write n x target = n2 × (n2 + 1)/2. From this expression, we can derive, target = n × (n2 + 1)/2
C++
#include<iostream>#include<vector>usingnamespacestd;boolmagicSquare(vector<vector<int>>&mat){intn=mat.size();inttarget=n*(n*n+1)/2;// track uniquenessvector<int>visited(n*n+1,0);intd1=0,d2=0;for(inti=0;i<n;i++){introwSum=0,colSum=0;for(intj=0;j<n;j++){intvalRow=mat[i][j];intvalCol=mat[j][i];// range + duplicate checkif(valRow<1||valRow>n*n||visited[valRow])returnfalse;visited[valRow]=1;rowSum+=valRow;colSum+=valCol;// diagonalsif(i==j)d1+=valRow;if(i+j==n-1)d2+=valRow;}if(rowSum!=target||colSum!=target)returnfalse;}returnd1==target&&d2==target;}intmain(){vector<vector<int>>mat={{2,7,6},{9,5,1},{4,3,8}};cout<<(magicSquare(mat)?"true":"false");return0;}
Java
importjava.util.Scanner;publicclassGFG{staticbooleanmagicSquare(int[][]mat){intn=mat.length;inttarget=n*(n*n+1)/2;boolean[]visited=newboolean[n*n+1];intd1=0,d2=0;for(inti=0;i<n;i++){introwSum=0,colSum=0;for(intj=0;j<n;j++){intvalRow=mat[i][j];intvalCol=mat[j][i];// range + duplicate checkif(valRow<1||valRow>n*n||visited[valRow])returnfalse;visited[valRow]=true;rowSum+=valRow;colSum+=valCol;// diagonalsif(i==j)d1+=valRow;if(i+j==n-1)d2+=valRow;}if(rowSum!=target||colSum!=target)returnfalse;}returnd1==target&&d2==target;}publicstaticvoidmain(String[]args){int[][]mat={{2,7,6},{9,5,1},{4,3,8}};System.out.println(magicSquare(mat)?"true":"false");}}
Python
defmagicSquare(mat):n=len(mat)target=n*(n*n+1)//2visited=[0]*(n*n+1)d1=d2=0foriinrange(n):row_sum=col_sum=0forjinrange(n):val_row=mat[i][j]val_col=mat[j][i]# range + duplicate checkifval_row<1orval_row>n*norvisited[val_row]:returnFalsevisited[val_row]=1row_sum+=val_rowcol_sum+=val_col# diagonalsifi==j:d1+=val_rowifi+j==n-1:d2+=val_rowifrow_sum!=targetorcol_sum!=target:returnFalsereturnd1==targetandd2==target# Driver Codeif__name__=="__main__":mat=[[2,7,6],[9,5,1],[4,3,8]]print("true"ifmagicSquare(mat)else"false")
C#
usingSystem;classGFG{staticboolmagicSquare(int[][]mat){intn=mat.Length;inttarget=0;// Compute target sum (first row)for(intj=0;j<n;j++)target+=mat[0][j];// Track valuesint[]visited=newint[n*n+1];for(inti=0;i<n;i++){introwSum=0,colSum=0;for(intj=0;j<n;j++){rowSum+=mat[i][j];colSum+=mat[j][i];intval=mat[i][j];// Check valid range and duplicatesif(val<1||val>n*n||visited[val]==1)returnfalse;visited[val]=1;}// Validate row and column sumsif(rowSum!=target||colSum!=target)returnfalse;}intd1=0,d2=0;// Check diagonalsfor(inti=0;i<n;i++){d1+=mat[i][i];d2+=mat[i][n-i-1];}returnd1==target&&d2==target;}staticvoidMain(){int[][]mat={newint[]{2,7,6},newint[]{9,5,1},newint[]{4,3,8}};Console.WriteLine(magicSquare(mat)?"true":"false");}}