Time Complexity of No of Islands question - data-structures

what is the time complexity of below-written code-
i think the complexity should be O(rcn)
where n= maximum size island
but on gfg they had written the complexity is O(V+E)
void bfs(int r, int c, vector < vector < char >> & grid) {
queue < pair < int, int >> q;
int row[4] = {-1,0,1,0};
int col[4] = {0,1,0,-1};
q.push(make_pair(r, c));
while (!q.empty()) {
pair < int, int > p = q.front();
int x = p.first;
int y = p.second;
q.pop();
for (int i = 0; i < 4; i++) {
if (x + row[i] < grid.size() && y + col[i] < grid[0].size() && x + row[i] >= 0 && y + col[i] >= 0 && grid[x + row[i]][y + col[i]] == '1') {
q.push(make_pair(x + row[i], y + col[i]));
grid[x + row[i]][y + col[i]] = '0';
}
}
}
}
int numIslands(vector < vector < char >> & grid) {
int count = 0;
int r = grid.size();
if (r == 0)
return count;
int c = grid[0].size();
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (grid[i][j] == '1') {
bfs(i, j, grid);
count++;
}
}
}
return count;
}

Related

Finding number of pairs, product of whose indices is divisible by another number X

Given an array and some value X, find the number of pairs such that i < j , a[i] = a[j] and (i * j) % X == 0
Array size <= 10^5
I am thinking of this problem for a while but only could come up with the brute force solution(by checking all pairs) which will obviously time-out [O(N^2) time complexity]
Any better approach?
First of all, store separate search structures for each distinct A[i] as we iterate.
i * j = k * X
i = k * X / j
Let X / j be some fraction. Since i is an integer, k would be of the form m * least_common_multiple(X, j) / X, where m is natural.
Example 1: j = 20, X = 60:
lcm(60, 20) = 60
matching `i`s would be of the form:
(m * 60 / 60) * 60 / 20
=> m * q, where q = 3
Example 2: j = 6, X = 2:
lcm(2, 6) = 6
matching `i`s would be of the form:
(m * 6 / 2) * 2 / 6
=> m * q, where q = 1
Next, I would consider how to efficiently query the number of multiples of a number in a sorted list of arbitrary naturals. One way is to hash the frequency of divisors of each i we add to the search structure of A[i]. But first consider i as j and add to the result the count of divisors q that already exist in the hash map.
JavaScript code with brute force testing at the end:
function gcd(a, b){
return b ? gcd(b, a % b) : a;
}
function getQ(X, j){
return X / gcd(X, j);
}
function addDivisors(n, map){
let m = 1;
while (m*m <= n){
if (n % m == 0){
map[m] = -~map[m];
const l = n / m;
if (l != m)
map[l] = -~map[l];
}
m += 1;
}
}
function f(A, X){
const Ais = {};
let result = 0;
for (let j=1; j<A.length; j++){
if (A[j] == A[0])
result += 1;
// Search
if (Ais.hasOwnProperty(A[j])){
const q = getQ(X, j);
result += Ais[A[j]][q] || 0;
// Initialise this value's
// search structure
} else {
Ais[A[j]] = {};
}
// Add divisors for j
addDivisors(j, Ais[A[j]]);
}
return result;
}
function bruteForce(A, X){
let result = 0;
for (let j=1; j<A.length; j++){
for (let i=0; i<j; i++){
if (A[i] == A[j] && (i*j % X) == 0)
result += 1;
}
}
return result;
}
var numTests = 1000;
var n = 100;
var m = 50;
var x = 100;
for (let i=0; i<numTests; i++){
const A = [];
for (let j=0; j<n; j++)
A.push(Math.ceil(Math.random() * m));
const X = Math.ceil(Math.random() * x);
const _brute = bruteForce(A, X);
const _f = f(A, X);
if (_brute != _f){
console.log("Mismatch!");
console.log(X, JSON.stringify(A));
console.log(_brute, _f);
break;
}
}
console.log("Done testing.")
Just in case If someone needed the java version of this answer - https://stackoverflow.com/a/69690416/19325755 explanation has been provided in that answer.
I spent lot of time in understanding the javascript code so I thought the people who are comfortable with java can refer this for better understanding.
import java.util.HashMap;
public class ThisProblem {
public static void main(String[] args) {
int t = 1000;
int n = 100;
int m = 50;
int x = 100;
for(int i = 0; i<t; i++) {
int[] A = new int[n];
for(int j = 0; j<n; j++) {
A[j] = ((int)Math.random()*m)+1;
}
int X = ((int)Math.random()*x)+1;
int optR = createMaps(A, X);
int brute = bruteForce(A, X);
if(optR != brute) {
System.out.println("Wrong Answer");
break;
}
}
System.out.println("Test Completed");
}
public static int bruteForce(int[] A, int X) {
int result = 0;
int n = A.length;
for(int i = 1; i<n; i++) {
for(int j = 0; j<i; j++) {
if(A[i] == A[j] && (i*j)%X == 0)
result++;
}
}
return result;
}
public static int gcd(int a, int b) {
return b==0 ? a : gcd(b, a%b);
}
public static int getQ(int X, int j) {
return X/gcd(X, j);
}
public static void addDivisors(int n, HashMap<Integer, Integer> map) {
int m = 1;
while(m*m <= n) {
if(n%m == 0) {
map.put(m, map.getOrDefault(m, 0)+1);
int l = n/m;
if(l != m) {
map.put(l, map.getOrDefault(l, 0)+1);
}
}
m++;
}
}
public static int createMaps(int[] A, int X) {
int result = 0;
HashMap<Integer, HashMap<Integer, Integer>> contentsOfA = new HashMap<>();
int n = A.length;
for(int i = 1; i<n; i++) {
if(A[i] == A[0])
result++;
if(contentsOfA.containsKey(A[i])) {
int q = getQ(X, i);
result += contentsOfA.get(A[i]).getOrDefault(q, 0);
} else {
contentsOfA.put(A[i], new HashMap<>());
}
addDivisors(i, contentsOfA.get(A[i]));
}
return result;
}
}

Runtime error for large inputs for sorting ( quicksort)

This is a very simple program where the user inputs (x,y) coordinates and distance 'd' and the program has to find out the number of unrepeated coordinates from (x,y) to (x+d,y).
For eg: if input for one test case is: 4,9,2 then the unrepeated coordinates are (4,9),(5,9) and (6,9)(x=4,y=9,d=2). I have used a sorting algorithm as mentioned in the question (to keep track of multiple occurrences) however the program shows runtime error for test cases beyond 30. Is there any mistake in the code or is it an issue with my compiler?
For a detailed explanation of question: https://www.hackerearth.com/practice/algorithms/sorting/merge-sort/practice-problems/algorithm/missing-soldiers-december-easy-easy/
#include <stdio.h>
#include <stdlib.h>
int partition(int *arr, int p, int r) {
int x;
x = arr[r];
int tmp;
int i = p - 1;
for (int j = p; j <= r - 1; ++j) {
if (arr[j] <= x) {
i = i + 1;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
tmp = arr[i + 1];
arr[i + 1] = arr[r];
arr[r] = tmp;
return (i + 1);
}
void quicksort(int *arr, int p, int r) {
int q;
if (p < r) {
q = partition(arr, p, r);
quicksort(arr, p, q - 1);
quicksort(arr, q + 1, r);
}
}
int count(int A[],int ct) {
int cnt = 0;
for (int i = 0; i < ct; ++i) {
if (A[i] != A[i + 1]) {
cnt++;
}
}
return cnt;
}
int main() {
int t;
scanf("%d", &t);
long int tmp, y, d;
int ct = 0;
int i = 0;
int x[1000];
int j = 0;
for (int l = 0; l < t; ++l) {
scanf("%d%d%d", &tmp, &y, &d);
ct = ct + d + 1; //this counts the total no of coordinates for each (x,y,d)
for (int i = 0; i <= d; ++i) {
x[j] = tmp + i; //storing all possible the x and x+d coordinates
j++;
}
}
int cnt;
int p = ct - 1;
quicksort(x, 0, p); //quicksort sorting
for (int l = 0; l < ct; ++l) {
printf("%d ", x[l]); //prints sorted array not necessary to question
}
cnt = count(x, ct); //counts the number of non-repeated vertices
printf("%d\n", cnt);
}
The problem was the bounds of the array int x[1000] is not enough for the data given below.

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;
}

Find the largest rectangle dimension

Given a matrix of ‘O’ and ‘X’, find the largest rectangle whose sides consist of ‘X’
Example 1
XXXXX
X0X0X
XXXXX
XXXXX
Output : largest rectangle size is 4 x 5
Example 2
0X0XX
X0X0X
XXXXX
XXXXX
Output: largest rectangle size is 2 x 5 (last two rows of the matrix)
I am able to make o(n4) algorithm in which I look for each combination. Can anybody please give some hints or idea for better optimized algorithm.
My Code:
#include<iostream>
#include<vector>
using namespace std;
int arr[1001][1001];
int check(int left[][1001],int up[][1001], int m, int n, int leftx, int lefty, int rightx, int righty)
{
if(((righty - lefty) == (left[rightx][righty] - left[rightx][lefty])) and ((left[leftx][righty] - left[leftx][lefty]) ==( righty - lefty)))
{
if(((rightx - leftx) == ( up[rightx][righty] - up[leftx][righty] )) and ((up[rightx][lefty] - up[leftx][lefty]) == rightx - leftx))
{
return (2*(left[leftx][righty] - left[leftx][lefty] + up[rightx][lefty] - up[leftx][lefty] ));
}
}
return 0;
}
void solve(int arr[][1001], int m, int n)
{
int left[1001][1001];
int up[1001][1001];
for(int i=0 ; i<m ;i++)
{
int prev = 1;
for(int j=0 ; j<n ;j++)
{
if(arr[i][j] == 1)
{
left[i][j] = prev;
++prev;
}
else if(arr[i][j] == -1)
{
left[i][j] = -1;
prev =1;
}
}
}
for(int i=0 ; i<n ;i++)
{
int prev = 1;
for(int j=0 ; j<m ;j++)
{
if(arr[j][i] == 1)
{
up[j][i] = prev;
++prev;
}
else if(arr[j][i] == -1)
{
up[j][i] = -1;
prev =1;
}
}
}
int max = 0;
int max_col = 0;
int max_row = 0;
for(int i =0; i < m-1 ; i++)
{
for(int j =0; j<n-1; j++)
{
for(int k = m-1 ; k >i ; k--)
{
for(int l = n-1; l >j ; l--)
{
if(((k-i > max_row) || (l-j > max_col)))
{
int maxi = check(left,up,m,n,i,j,k,l);
if(maxi > max)
{
max = maxi;
max_col = l-j;
max_row = k-i;
}
}
}
}
}
}
cout<<"Dimension = "<<max_col<<"\t"<<max_row<<endl;
}

how to generate Chase's sequence

In the draft section 7.2.1.3 of The art of computer programming, generating all combinations, Knuth introduced Algorithm C for generating Chase's sequence.
He also mentioned a similar algorithm (based on the following equation) working with index-list without source code (exercise 45 of the draft).
I finally worked out a c++ version which I think is quite ugly. To generate all C_n^m combination, the memory complexity is about 3 (m+1) and the time complexity is bounded by O(m n^m)
class chase_generator_t{
public:
using size_type = ptrdiff_t;
enum class GET : char{ VALUE, INDEX };
chase_generator_t(size_type _n) : n(_n){}
void choose(size_type _m){
m = _m;
++_m;
index.resize(_m);
threshold.resize(_m + 1);
tag.resize(_m);
for (size_type i = 0, j = n - m; i != _m; ++i){
index[i] = j + i;
tag[i] = tag_t::DECREASE;
using std::max;
threshold[i] = max(i - 1, (index[i] - 3) | 1);
}
threshold[_m] = n;
}
bool get(size_type &x, size_type &y, GET const which){
if (which == GET::VALUE) return __get<false>(x, y);
return __get<true>(x, y);
}
size_type get_n() const{
return n;
}
size_type get_m() const{
return m;
}
size_type operator[](size_t const i) const{
return index[i];
}
private:
enum class tag_t : char{ DECREASE, INCREASE };
size_type n, m;
std::vector<size_type> index, threshold;
std::vector<tag_t> tag;
template<bool GetIndex>
bool __get(size_type &x, size_type &y){
using std::max;
size_type p = 0, i, q;
find:
q = p + 1;
if (index[p] == threshold[q]){
if (q >= m) return false;
p = q;
goto find;
}
x = GetIndex ? p : index[p];
if (tag[p] == tag_t::INCREASE){
using std::min;
increase:
index[p] = min(index[p] + 2, threshold[q]);
threshold[p] = index[p] - 1;
}
else if (index[p] && (i = (index[p] - 1) & ~1) >= p){
index[p] = i;
threshold[p] = max(p - 1, (index[p] - 3) | 1);
}
else{
tag[p] = tag_t::INCREASE;
i = p | 1;
if (index[p] == i) goto increase;
index[p] = i;
threshold[p] = index[p] - 1;
}
y = index[p];
for (q = 0; q != p; ++q){
tag[q] = tag_t::DECREASE;
threshold[q] = max(q - 1, (index[q] - 3) | 1);
}
return true;
}
};
Does any one has a better implementation, i.e. run faster with the same memory or use less memory with the same speed?
I think that the C code below is closer to what Knuth had in mind. Undoubtedly there are ways to make it more elegant (in particular, I'm leaving some scaffolding in case it helps with experimentation), though I'm skeptical that the array w can be disposed of. If storage is really important for some reason, then steal the sign bit from the a array.
#include <stdbool.h>
#include <stdio.h>
enum {
N = 10,
T = 5
};
static void next(int a[], bool w[], int *r) {
bool found_r = false;
int j;
for (j = *r; !w[j]; j++) {
int b = a[j] + 1;
int n = a[j + 1];
if (b < (w[j + 1] ? n - (2 - (n & 1)) : n)) {
if ((b & 1) == 0 && b + 1 < n) b++;
a[j] = b;
if (!found_r) *r = j > 1 ? j - 1 : 0;
return;
}
w[j] = a[j] - 1 >= j;
if (w[j] && !found_r) {
*r = j;
found_r = true;
}
}
int b = a[j] - 1;
if ((b & 1) != 0 && b - 1 >= j) b--;
a[j] = b;
w[j] = b - 1 >= j;
if (!found_r) *r = j;
}
int main(void) {
typedef char t_less_than_n[T < N ? 1 : -1];
int a[T + 1];
bool w[T + 1];
for (int j = 0; j < T + 1; j++) {
a[j] = N - (T - j);
w[j] = true;
}
int r = 0;
do {
for (int j = T - 1; j > -1; j--) printf("%x", a[j]);
putchar('\n');
if (false) {
for (int j = T - 1; j > -1; j--) printf("%d", w[j]);
putchar('\n');
}
next(a, w, &r);
} while (a[T] == N);
}

Resources