Count null diagonals in a matrix - matrix

I'm trying to create a program that counts the number of null diagonals in a square matrix, but I can't seem to find the correct way of making my index run correctly through the matrix. Here's the incorrect code I've got so far:
# include<stdio.h>
# define MAX 100
int DiagonNull (int n, int A[MAX][MAX]) {
int i, j, count, null;
banda = 0;
for(i = n - 1; i >= 0; i--){
count = 0;
for(j = 0; j <= n && j < i - 1; j++){
if (A[i][j] == 0)
count++;
}
if (count == n - i) /* n - i = number of elements in diagonal */
null++;
else
i = - 1;
}
return null;
}
int main () {
int n, A[MAX][MAX], i, j, null;
printf ("Enter value of n to create a square matrix A of order n: ");
scanf ("%d", &n);
printf ("Enter the elements of matrix A: ");
for (i = 0; i < n; i++){
for (j = 0; j < n; j++){
scanf("%d", &A[i][j]);
}
}
null = DiagonNull (n, A);
printf ("Matrix has null %d diagonals", null);
return 0;
}

Related

Top down approach 01 Matrix

I new do dynamic programming and I am attempting the following problem on leetcode: 01 Matrix
Problem: Given an m x n binary matrix mat, return the distance of the nearest 0 for each cell. The distance between two adjacent cells is 1.
I have attempted the problem using top-down dynamic programming but cannot seem to get the right answer for all the test cases. In all most all cases, the matrix is almost optimized except for a few values. My algorithm entails finding a '1' and then doing a depth first search in all 4 directions and then taking the minimum of the values + 1 and saving that to the memoization table (ans[][]).
I have tried to search for a top down approach but all most all the solutions are bottom up. Can anyone please help me understand why taking the minimum of the steps in all 4 directions using memoization doesn't not yield an optimal solution or what my solution is missing?
class Solution {
public int[][] updateMatrix(int[][] mat) {
int m = mat.length;
int n = mat[0].length;
int[][] ans = new int[m][n];
for(int i = 0; i <m; i++){
for(int j = 0; j <n; j++){
if(mat[i][j] == 0){
ans[i][j] = 0;
}
else{
ans[i][j] = -1;
}
}
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(ans[i][j] == - 1){
boolean[][] visited = new boolean[m][n];
ans[i][j] = dfs(i, j, m, n, mat, ans, visited);
}
}
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
boolean[][] visited = new boolean[m][n];
ans[i][j] = Math.min(ans[i][j], dfs(i, j, m, n, mat, ans, visited));
}
}
return ans;
}
public int dfs(int i, int j, int m, int n, int[][]mat, int[][] ans, boolean[][] visited){
if(i >= m || i < 0 || j >=n || j < 0|| visited[i][j]){
return Integer.MAX_VALUE;
}
if(mat[i][j] == 0){
return 0;
}
if(ans[i][j] != -1){
return ans[i][j];
}
visited[i][j] = true;
int up = dfs(i - 1, j, m, n, mat, ans, visited);
int down = dfs(i + 1, j, m, n, mat, ans, visited);
int left = dfs( i, j - 1, m, n, mat, ans, visited);
int right = dfs(i, j + 1, m, n, mat, ans,visited);
visited[i][j] = false;
ans[i][j] = Math.min (up, Math.min(down, Math.min(left, right))) + 1;
return ans[i][j];
}
}
The 3 double-loops at the beginning could be reduced to one double-loop, the 3rd one seems to be completely superfluous. Dfs is not working here. E.g. you will go 4 fields up 1 left and 4 fields down and save 9 but actually that field could be reached in 1 step to the left, you just ignore it because you already have a result. Even if you would fix the problems, this is still O((nm)^2) instead of O(nm). For an O(nm) solution you can initialize the result with 0 where you have a 0, with -1 where there is no 0 next to it and 1 where you have a 1 with a 0 next to it, additionally add the position of this 1 to a list. Initialize c to 2. Go through the list and check the positions up, left, right and down, if it is a -1 in the result replace it by c and add this position to a new list. Replace the list by the new list, increment c and go through the list again and again until it is empty.
There is also a working DFS implementation that is easier to understand:
https://leetcode.com/problems/01-matrix/discuss/732601/DFS-O(1)-Space
class Solution {
public int[][] updateMatrix(int[][] dist) {
int m = dist.length;
int n = dist[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dist[i][j] != 0) {
dist[i][j] = Integer.MAX_VALUE;
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dist[i][j] == 0) {
dfs(dist, i - 1, j, 1);
dfs(dist, i + 1, j, 1);
dfs(dist, i, j - 1, 1);
dfs(dist, i, j + 1, 1);
}
}
}
return dist;
}
private void dfs(int[][] dist, int i, int j, int value) {
if (i >= 0 && i < dist.length && j >= 0 && j < dist[0].length && value < dist[i][j]) {
dist[i][j] = value;
dfs(dist, i - 1, j, value + 1);
dfs(dist, i + 1, j, value + 1);
dfs(dist, i, j - 1, value + 1);
dfs(dist, i, j + 1, value + 1);
}
}
}

Please tell me how can I pass the two dimensional array here to the called function 'getCount', also suggest any better ways to approach

vector A[] initially contains all the elements, I've copied all elements to the array arr
The task is to get the count of Islands in given elements
int getCount(int *arr, int r, int c, int row, int column)
{
if (r < 0 || c < 0 || r > row || c > column)
return 0;
if (arr[r][c] == 0)
return 0;
arr[r][c] = 0;
int val = 1;
for (int i = r - 1; r < r + 1; r++)
for (int j = -1; j < c + 1; c++)
{
if (i != r || j != c)
getCount(arr, r, c, row, column);
}
return val;
}
int findIslands(vector<int> A[], int N, int M)
{
int arr[N][M];
for(int i=0;i<N;i++)
for(int j=0;j<M;j++)
{
int temp=(i*M)+j;
arr[i][j]=A[temp];
}
for(int row=0;row<N;row++)
for (int column = 0; column < M; column++)
{
if (arr[row][column] == 1)
count += getCount((int *)arr, row, column, N, M);
}
return count;
}

Maximal Square with 0 inside

The question Maximal Square in https://leetcode.com/problems/maximal-square/description/ is easy to solve by DP. But how to solve the following up question:
Similar as Maximal Square question, but allows 0's inside a square, "inside" means the border of the square must be all 1.
For example, given the following matrix:
1 0 1 0 0
1 0 1 1 1
1 1 1 0 1
1 0 1 1 1
Return 9.
Update: Because the 3*3 matrix in the right bottom corner matches the requirement, the border must be all 1, and there can be 0 inside the square.
I thought up a O(n^3) algorithm: take maze[i][j] as the right bottom corner of the square if maze[i][j] == 1, enumerate the edge length of the square. If edge length is 3, consider whether maze[i - 2][j - 2], maze[i][j - 2], maze[i - 2][j], maze[i][j] forms a square with the numbers in each edge are all 1.
Is there any better algorithm?
Your problem can be solved in O (n * m) time and space complexity, where n is total rows and m is total columns in matrix. You may look at the code below where I have commented out to make it understandable.
Please, let me know if you have any doubt.
#include <bits/stdc++.h>
using namespace std;
void precalRowSum(vector< vector<int> >& grid, vector< vector<int> >&rowSum, int n, int m) {
// contiguous sum upto jth position in ith row
for (int i = 0; i < n; ++i) {
int sum = 0;
for (int j = 0; j < m; ++j) {
if (grid[i][j] == 1) {
sum++;
} else {
sum = 0;
}
rowSum[i][j] = sum;
}
}
}
void precalColSum(vector< vector<int> >& grid, vector< vector<int> >&colSum, int n, int m) {
// contiguous sum upto ith position in jth column
for (int j = 0; j < m; ++j) {
int sum = 0;
for (int i = 0; i < n; ++i) {
if (grid[i][j] == 1) {
sum++;
} else {
sum = 0;
}
colSum[i][j] = sum;
}
}
}
int solve(vector< vector<int> >& grid, int n, int m) {
vector< vector<int> >rowSum(n, vector<int>(m, 0));
vector< vector<int> >colSum(n, vector<int>(m, 0));
// calculate rowwise sum for 1
precalRowSum(grid, rowSum, n, m);
// calculate colwise sum for 1
precalColSum(grid, colSum, n, m);
vector< vector<int> >zerosHeight(n, vector<int>(m, 0));
int ans = 0;
for (int i = 0; i < (n - 1); ++i) {
for (int j = 0; j < m; ++j) {
zerosHeight[i][j] = ( grid[i][j] == 0 );
if (grid[i][j] == 0 && i > 0) {
zerosHeight[i][j] += zerosHeight[i - 1][j];
}
}
if (i == 0) continue;
// perform calculation on ith row
for (int j = 1; j < m; ) {
int height = zerosHeight[i][j];
if (!height) {
j++;
continue;
}
int cnt = 0;
while (j < m && height == zerosHeight[i][j]) {
j++;
cnt++;
}
if ( j == m) break;
if (cnt == height && (i - cnt) >= 0 ) {
// zeros are valid, now check validity for boundries
// Check validity of upper boundray, lower boundary, left boundary, right boundary respectively
if (rowSum[i - cnt][j] >= (cnt + 2) && rowSum[i + 1][j] >= (cnt + 2) &&
colSum[i + 1][j - cnt - 1] >= (cnt + 2) && colSum[i + 1][j] >= (cnt + 2) ){
ans = max(ans, (cnt + 2) * (cnt + 2) );
}
}
}
}
return ans;
}
int main() {
int n, m;
cin>>n>>m;
vector< vector<int> >grid;
for (int i = 0; i < n; ++i) {
vector<int>tmp;
for (int j = 0; j < m; ++j) {
int x;
cin>>x;
tmp.push_back(x);
}
grid.push_back(tmp);
}
cout<<endl;
cout<< solve(grid, n, m) <<endl;
return 0;
}

How to calculate number of partitions of n?

How can I calculate number of partitions of n mod 1e9+7, where n<=50000.
See http://oeis.org/A000041 .
Here is the source problem http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1259 (In Chinese)
Simply applying the formula: a(n) = (1/n) * Sum_{k=0..n-1} d(n-k)*a(k) gave me an O(n^2) solution.
typedef long long ll;
ll MOD=1e9+7;
ll qp(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1) ans=ans*a%MOD;
a=a*a%MOD;
b>>=1;
}
return ans;
}
ll a[50003],d[50003];
#define S 1000
int main()
{
for(int i=1; i<=S; i++)
{
for(int j=1; j<=S; j++)
{
if(i%j==0) d[i]+=j;
}
d[i]%=MOD;
}
a[0]=1;
for(int i=1; i<=S; i++)
{
ll qwq=0;
for(int j=0; j<i; j++) qwq=qwq+d[i-j]*a[j]%MOD;
qwq%=MOD;
a[i]=qwq*qp(i,MOD-2)%MOD;
}
int n;
cin>>n;
cout<<a[n]<<"\n";
}
I would solve it with a different approach.
Dynamic Programming:
DP[N,K] = number of partitions of N using only numbers 1..K
DP[0,k] = 1
DP[n,0] = 0
DP[n,k] when n<0 = 0
DP[n,k] when n>0 = DP[n-k,k] + DP[n,k-1]
Recursive implementation using memoization:
ll partition(ll n, ll max){
if (max == 0)
return 0;
if (n == 0)
return 1;
if (n < 0)
return 0;
if (memo[n][max] != 0)
return memo[n][max];
else
return (memo[n][max] = (partition(n, max-1) + partition(n-max,max)));
}
Live-Example

How to find the number of blobs in a 2d matrix?

How can I find the number of blobs in a 2d matrix? SIZE MxN
A blob is a block of continuous X pixels. where the matrix contains X and O
XOOOXO
OXOXOX
XXOOXO
I would like to use 8-neighbourship (see here). So I would expect 2 blobs to be found in above example.
The idea is simple: Mark each continuous blob and count how many blobs were marked.
Here is some pseudo-code (you did not specify a programming language) to get you started:
numBlobs = 0;
foreach(item in matrix)
{
res = Visit(item);
if(res > 0)
{
numBlobs = numBlobs + 1;
}
}
return numBlobs;
The Visit function/method looks like this:
Visit(item)
{
marked = 0;
if(item.IsX() && !IsItemMarked(neighbour))
{
MarkItemAsVisited(item);
marked = 1;
foreach(neighbour in GetNeighbours(item))
{
marked = marked + Visit(neighbour);
}
}
return marked;
}
All you have to do is to implement the other fucntions/methods but they are pretty straightforward.
public static void main(String[] args) {
int[][] matrix = new int[6][5];
System.out.println(matrix.length);
for (int i=0; i < matrix.length; i++) {
for (int j=0; j < matrix[i].length; j++) {
matrix[i][j] = 0;
}
}
matrix[0][3] = 1;
matrix[1][1] = 1;
matrix[1][3] = 1;
matrix[2][1] = 1;
matrix[2][2] = 1;
matrix[2][3] = 1;
matrix[4][0] = 1;
matrix[4][4] = 1;
matrix[5][2] = 1;
matrix[5][3] = 1;
matrix[5][4] = 1;
System.out.println(findBlobCount(matrix, matrix.length, matrix[0].length));
}
static int findBlobCount (int matrix[][], int rowCount, int colCount)
{
int visited[][] = new int[rowCount][colCount]; // all initialized to false
int count=0;
for (int i=0; i<rowCount; i++)
{
for (int j=0; j<colCount; j++)
{
if (matrix[i][j] == 1 && visited[i][j] == 0) // unvisited black cell
{
markVisited (i,j, matrix, visited, rowCount, colCount);
count++;
}
}
}
return count;
}
static int markVisited (int i, int j, int [][]matrix, int [][]visited, int rowCount, int colCount)
{
if (i < 0 || j < 0)
return 0;
if (i >= rowCount || j >= colCount)
return 0;
if (visited[i][j] == 1) // already visited
return 1;
if (matrix[i][j] == 0) // not a black cell
return 0;
visited[i][j] = 1;
// recursively mark all the 4 adjacent cells - right, left, up and down
return markVisited (i+1, j, matrix, visited, rowCount, colCount)
+ markVisited (i-1, j, matrix, visited, rowCount, colCount)
+ markVisited (i, j+1, matrix, visited, rowCount, colCount)
+ markVisited (i, j-1, matrix, visited, rowCount, colCount);
}

Resources