leetcode - number of islands, RecursionError - recursion

I'm trying to solve the famous problem of "number of islands" from leetcode. (link : https://leetcode.com/problems/number-of-islands/)
I solved this solution using BFS, but I got this error :
"RecursionError: maximum recursion depth exceeded in comparison"
Why I get this error?
I cant figure why.
Here is my code:
def numIslands(grid):
islands = 0
for i in range(0, len(grid)):
for j in range(0, len(grid[0])):
if(grid[i][j] == "1"):
islands += 1
marksZero(grid, i, j)
print(islands)
return islands
def marksZero(grid, i, j):
if(grid[i][j] == "0"):
return
grid[i][j] = 0
if(i - 1 >= 0):
marksZero(grid, i - 1, j)
if(i + 1 < len(grid)):
marksZero(grid, i + 1, j)
if(j - 1 >= 0):
marksZero(grid, i, j - 1)
if(j + 1 < len(grid[0])):
marksZero(grid, i, j + 1)
numIslands([["1","1","1","1","0"],["1","1","0","1","0"],["1","1","0","0","0"],["0","0","0","0","0"]])

You are assigning int instead of string to your grid,therefore condition creates infinite loop.
Change grid[i][j] = "0"
def numIslands(grid):
islands = 0
for i in range(0, len(grid)):
for j in range(0, len(grid[0])):
if(grid[i][j] == "1"):
islands += 1
marksZero(grid, i, j)
print(islands)
return islands
def marksZero(grid, i, j):
if(grid[i][j] == "0"):
return
grid[i][j] = "0"
if(i - 1 >= 0):
marksZero(grid, i - 1, j)
if(i + 1 < len(grid)):
marksZero(grid, i + 1, j)
if(j - 1 >= 0):
marksZero(grid, i, j - 1)
if(j + 1 < len(grid[0])):
marksZero(grid, i, j + 1)
numIslands([["1", "1", "1", "1", "0"],
["1", "1", "0", "1", "0"],
["1", "1", "0", "0", "0"],
["0", "0", "0", "0", "0"]])

you need to add some visit matrix to make sure you are in each cell only once
something like that
visit = [[False ]* 5 ]* 4
def marksZero(grid, i, j):
if visit[i][j]:
return
visit[i][j]=True

Related

If lattice in function

I am trying to create a function that returns different values when the variable is in different ranges.
nhpp_lambda <- function(t) {
for (t in 1:365) {
if (t >= "1" && t <= "59")
lambda = 20.83
else if (t >= "60" && t <= "151")
lambda = 11.02
else if (t >= "152" && t <= "243")
lambda = 11.68
else if (t >= "244" && t <= "334")
lambda = 26.41
else if (t >= "335" && t <= "365")
lambda = 20.83
}
return(lambda)
}
how come this doesn't work? it still just always returns 20.83??
In the function you have defined you return the value of lambda after the loop has finished, and in the last iteration of the loop, the value is always 20.83. If you remove the loop, it will work, e.g.,
nhpp_lambda <- function (t) {
if (t >= 1 && t <= 59)
lambda = 20.83
else if (t >= 60 && t <= 151)
lambda = 11.02
else if (t >= 152 && t <= 243)
lambda = 11.68
else if (t >= 244 && t <= 334)
lambda = 26.41
else if (t >= 335 && t <= 365)
lambda = 20.83
return(lambda)
}
nhpp_lambda(5)
nhpp_lambda(55)
nhpp_lambda(120)
nhpp_lambda(285)
nhpp_lambda(340)
Firstly, you're taking $t$ as a function argument, but then defining $t$ through the loop $1:365$, so that $t$ cycles in values from $1,2,\dots,365$. Remove the for() loop, it serves no purpose.
Secondly, you're comparing a number $t$ to strings "1","59",etc. Remove the quoations, you should be comparing $t$ to integers not characters/strings. Here is the correct code
nhpp_lambda <- function(t) {
if (t >= 1 && t <= 59)
lambda = 20.83
else if (t >= 60 && t <= 151)
lambda = 11.02
else if (t >= 152 && t <= 243)
lambda = 11.68
else if (t >= 244 && t <= 334)
lambda = 26.41
else if (t >= 335 && t <= 365)
lambda = 20.83
return(lambda)
}

Converting recursive formulate into pseudocode using memoization

i've been trying to turn the recurrence formula underneath into a pseudocode that uses memoization, however currently all i know is my below attempt is incorrect, is anyone able to point me in the right direction?
My recurrence formula:
N(C,i) =
1 if C = 0
0 if i=0 or C<0}
N(C-p_i, i-1) + N(C, i-1) otherwise
My current attempt:
MEM-N(C, i, r)
if r[i] >= 0 then
return r[i]
if i = 0 and r[i] >= 0 or C < 0 and r[i] >= 0 then
return 0
else if C = 0 and r[i] >= 0 then
return 1
else
q = -$\infty$
q = MEM-N(C - $p_i$, i-1) + MEM-N(C,i - x, r)
r[i] = q
return q
Following on from the comments:
MEM-N(C, i, r)
if C = 0 then
return 1
else if i = 0 or C < 0 then
return 0
else if r[i] >= 0 then
return r[i] # move here
else
q = MEM-N(C - p_i, i - 1, r) + MEM-N(C, i - 1, r) # fix
r[i] = q
return q

Counting lengths of subseries

Imagine series of numbers like
c(21,22,23,30,31,32,34,35,36,37,38,50,NA,52)
where subseries are defined as: x[t] is a part of some subserie if x[t] = x[t-1] + 1?
So in the example above we have the following series:
c(21,22,23,30,31,32,34,35,36,37,38,50,NA,52)
## 1 1 1 2 2 2 3 3 3 3 3 4 - 5 # serie ID
## 3 | 3 | 5 | 1 | | 1 # length
What would be the most efficient way of tagging the subseries and counting their lengths (as a single function or two separate ones)?
We can get the difference between the adjacent elements, check whether it is equal to 1, get the cumulative sum, and use that as group to get the length of the vector
unname(tapply(v1, cumsum(c(TRUE, diff(replace(v1, is.na(v1), 0))!=1)), length))
#[1] 3 3 5 1 1 1
If we need the NA elements as ""
unname(tapply(v1, cumsum(c(TRUE, diff(replace(v1, is.na(v1), 0))!=1)),
function(x) if(all(is.na(x))) "" else length(x)))
#[1] "3" "3" "5" "1" "" "1"
Or a variation posted by #DavidArenburg with rle
rle(cumsum(c(TRUE, diff(replace(v1, is.na(v1), 0))!=1)))$lengths
I'm accepting the answer by akrun (with contribution by David Arenburg), but for the reference I provide a Rcpp solution I created in the meantime.
NumericVector cpp_seriesLengths(NumericVector x) {
int n = x.length();
if (n == 1)
return wrap(1);
NumericVector out(n);
int tmpCount = 1;
int prevStart = 0;
for (int i = 0; i < (n-1); i++) {
if ( x[i] == (x[i+1] - 1) ) {
tmpCount += 1;
} else {
for (int j = prevStart; j <= i; j++)
out[j] = tmpCount;
tmpCount = 1;
prevStart = i+1;
}
}
for (int j = prevStart; j < n; j++)
out[j] = tmpCount;
return out;
}

MATLAB to R Conversion: Append values to an existing empty array through for loop

I have the below code with me. This code was written originally in MATLAB. I have two questions here:
1) What would be the corresponding command in R for the below command in MATLAB:
duet(i).p = [];
2) In the below code I am getting all the correct 6 values for duet$n, but I am not getting correct values for duet$p. My question is how to append the values to an empty existing array duet$p[i] in R through the for loop iterations.
This line is not working in the below code:
duet$p[i] <- c(duet$p[i],j)
I might also have declared duet$p[i] <- array() incorrectly.
The values for duet.n and duet.p from MATLAB are:
duet.n
2 0 2 0 1 3
duet.p
[] [3,6] [] [1,3,5,6] [1,6] []
In R, I am getting duet$n values correctly, but I am not able to get the array kind of results for duet$p.
Any help to get the duet$p values would be appreciated.
x <- matrix(c(-1,2,4,1,7,4.2,3,0,1.2,-1.2,5.1,4,2,3.1,1.1,1,1,9,0,1,2,2,8,1,2,2,2,2,2,2),nrow=6,ncol=5,byrow=T)
fro=1;N=6;M=2;V=3;
F <- list(f=c())
duet = list()
for (i = 1 : N){
duet$n[i] = 0
duet$p[i] = array() ## Create an empty array
for (j in 1 : N){
dl = 0
de = 0
dm = 0
for (k = 1 : M){
if (x[i,V + k] < x[j,V + k]){
dl = dl + 1
} else if (x[i,V + k] == x[j,V + k]){
de = de + 1
} else{
dm = dm + 1
}
}
if (dl == 0 & de != M){
duet$n[i] = duet$n[i] + 1
} else if (dm == 0 & de != M){
duet$p[i] = c(duet$p[i],j)
}
}
if (duet$n[i] == 0){
x[i,6] = 1
F$f = c(F$f,i)
}
}
This appears to get the output you want:
x <- matrix(c(-1,2,4,1,7,4.2,3,0,1.2,-1.2,5.1,4,2,3.1,1.1,1,1,9,0,1,2,2,8,1,2,2,2,2,2,2),nrow=6,ncol=5,byrow=T)
fro=1;N=6;M=2;V=3;
F <- list(f=c())
duet = list(n=rep(0,N), p=lapply(1:N, function(x)c()))
for (i in 1 : N){
duet$n[i] = 0
#duet$p[[i]] = c() ## Create an empty array
#if(i==2) browser()
for (j in 1 : N){
k=1:M
dl <- sum(x[i,V + k] < x[j,V + k])
de <- sum(x[i,V + k] == x[j,V + k])
dm <- sum(x[i,V + k] > x[j,V + k])
if (dl == 0 & de != M){
duet$n[i] = duet$n[i] + 1
} else if (dm == 0 & de != M){
duet$p[[i]] = c(duet$p[[i]],j)
}
}
if (duet$n[i] == 0){
#x[i,6] = 1
F$f = c(F$f,i)
}
}
What have I done?
commented out the line x[i,6] =1, because there isn't an x[i,6], and I'm not sure what you meant it to be. You will need to sort this out.
Initialised duet$n as a vector
Initialised duet$p as a list of n empty vectors
removed the k loop as conditional counting in R can be done as the sum of elements where the condition is TRUE.
corrected the syntax of for loops: = became in
I think you're trying to do duet[i]$p instead of what you're doing. Also you need to initialize each cell as a list

How to find the number of binary numbers with the following constraints:

Given a binary digit count of n, and a maximum consecutive occurrence count of m, find the number of different possible binary numbers. Also, the leftmost and rightmost bit must be 1.
For example n = 5, and m = 3.
The count is 7:
10001
10011
10101
10111
11001
11011
11101
Notice we excluded 11111 because too many consecutive 1's exist in it.
This was an interview question I had recently, and It has been bothering me. I don't want to brute force check each number for legitimacy because n can be > 32.
Let's call a binary sequence almost valid if it starts with "1" and has at most m consecutive "1" digits.
For i = 1, ..., n and j = 0, ..., m let a(i, j) be the number of almost valid sequences with length i that end with exactly j consecutive "1" digits.
Then
a(1, 1) = 1 and a(1, j) = 0 for j != 1, because "1" is the only almost valid sequence of length one.
For n >= 2 and j = 0 we have a(i, 0) = a(i-1, 0) + a(i-1, 1) + ... + a(i-1, m), because appending "0" to any almost valid sequence of length i-1 gives an almost valid sequence of length i ending with "0".
For n >= 2 and j > 0 we have a(i, j) = a(i-1, j-1) because appending "1" to an almost valid sequence with i-1 trailing ones gives an almost valid sequence of length j with i trailing ones.
Finally, the wanted number is the number of almost valid sequences with length n that have a trailing "1", so this is
f(n, m) = a(n, 1) + a(n, 2) + ... + a(n, m)
Written as a C function:
int a[NMAX+1][MMAX+1];
int f(int n, int m)
{
int i, j, s;
// compute a(1, j):
for (j = 0; j <= m; j++)
a[1][j] = (j == 1);
for (i = 2; i <= n; i++) {
// compute a(i, 0):
s = 0;
for (j = 0; j <= m; j++)
s += a[i-1][j];
a[i][0] = s;
// compute a(i, j):
for (j = 1; j <= m; j++)
a[i][j] = a[i-1][j-1];
}
// final result:
s = 0;
for (j = 1; j <= m; j++)
s += a[n][j];
return s;
}
The storage requirement could even be improved, because only the last column of the matrix a is needed. The runtime complexity is O(n*m).
Without too much combinatorial insight you can tackle this with DP. Let's call left#n,mright the number of binary strings of length n, with no substring of consecutive 1's longer than m, beginning with the string left, and ending with the string right. Clearly, we want to find 1#n-2,m1.
The key observation is simply that left#n,mright = left+'1'#n-1,mright + left+'0'#n-1,mright
A simplistic implementation in js (not sure if it works for small m, and in general untested):
function hash(n,m) {
return _('1',n-2);
function _(left,n){
if (m+1 <= left.length && left.lastIndexOf('0') <= left.length-m-2)
return 0;
if (n==0)
return (m <= left.length &&
left.lastIndexOf('0') <= left.length-m-1 ? 0:1);
return _(left+'1',n-1) + _(left+'0',n-1);
}
}
hash(5,3); // 7
Of course this is more efficient than brute force, however the runtime complexity is still exponential, so it isn't practical for large values of n.

Resources