Skip to content

Commit

Permalink
Merge pull request #359 from dinesh-2047/rotate-array
Browse files Browse the repository at this point in the history
Rotate array problem solution added
  • Loading branch information
PRIYESHSINGH24 authored Jan 20, 2025
2 parents 5bdc2ad + 8b12b99 commit fdcfa1a
Show file tree
Hide file tree
Showing 16 changed files with 1,473 additions and 1,033 deletions.
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,8 @@
"C_Cpp_Runner.useLeakSanitizer": false,
"C_Cpp_Runner.showCompilationTime": false,
"C_Cpp_Runner.useLinkTimeOptimization": false,
"C_Cpp_Runner.msvcSecureNoWarnings": false
"C_Cpp_Runner.msvcSecureNoWarnings": false,
"files.associations": {
"StackImplement.C": "cpp"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#LEETCODE PROBLEM 37
Problem statement :- Write a program to solve a Sudoku puzzle by filling the empty cells.

A sudoku solution must satisfy all of the following rules:

Each of the digits 1-9 must occur exactly once in each row.
Each of the digits 1-9 must occur exactly once in each column.
Each of the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.
The '.' character indicates empty cells.

EXAMPLE :
Input: board = [["5","3",".",".","7",".",".",".","."],["6",".",".","1","9","5",".",".","."],[".","9","8",".",".",".",".","6","."],["8",".",".",".","6",".",".",".","3"],["4",".",".","8",".","3",".",".","1"],["7",".",".",".","2",".",".",".","6"],[".","6",".",".",".",".","2","8","."],[".",".",".","4","1","9",".",".","5"],[".",".",".",".","8",".",".","7","9"]]
Output: [["5","3","4","6","7","8","9","1","2"],["6","7","2","1","9","5","3","4","8"],["1","9","8","3","4","2","5","6","7"],["8","5","9","7","6","1","4","2","3"],["4","2","6","8","5","3","7","9","1"],["7","1","3","9","2","4","8","5","6"],["9","6","1","5","3","7","2","8","4"],["2","8","7","4","1","9","6","3","5"],["3","4","5","2","8","6","1","7","9"]]


SOLUTION :-

Intuition
This implementation optimizes the traditional backtracking approach by incorporating pre-computed constraints and heuristic decision-making, such as selecting the cell with the fewest valid candidates first. This strategy dramatically reduces unnecessary recursive calls and improves efficiency.

Approach
Pre-compute Constraints:

Maintain bitmasks (row, col, box) for each row, column, and 3x3 subgrid to track which numbers are already used.
Collect the coordinates of all empty cells (R and C).
Candidate Computation:

Use a helper function cand to compute valid numbers for a given cell using bitwise operations.
Calculate the number of valid candidates for each empty cell and store this information in cc.
Dynamic Candidate Recalculation:

Recalculate the number of valid candidates whenever a number is placed or removed during the backtracking process. This ensures the constraints are always up to date.
Optimized Backtracking:

Select the next cell to fill based on the cell with the fewest valid candidates (best), minimizing the branching factor.
Use a bitmask to generate possible numbers efficiently and iterate through them.
Perform recursive backtracking to fill cells.
Pruning:

If no valid candidates exist for any cell during the process, backtrack immediately.
Complexity
Time Complexity:

The optimization significantly reduces the effective branching factor. While the theoretical worst-case time complexity remains O(9ᵐ), where m is the number of empty cells, the heuristic often lowers the practical complexity to much more manageable levels.
Space Complexity:

O(m) for storing empty cell positions (R and C) and candidate counts (cc), where m is the number of empty cells.




CODE IN CPP :-
class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
int row[9]{}, col[9]{}, box[9]{};
vector<int> R, C, cc;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == '.') {
R.push_back(i);
C.push_back(j);
} else {
int d = board[i][j] - '1', m = 1 << d, b = (i / 3) * 3 + j / 3;
row[i] |= m; col[j] |= m; box[b] |= m;
}
}
}
cc.resize(R.size());
auto countBits = [&](int x) { int c = 0; while (x) { x &= x - 1; c++; } return c; };
function<int(int)> cand = [&](int idx) {
int r = R[idx], c = C[idx], b = (r / 3) * 3 + c / 3;
return countBits((~(row[r] | col[c] | box[b])) & 0x1ff);
};
auto recalc = [&]() {
for (int i = 0; i < (int)R.size(); i++) {
if (board[R[i]][C[i]] == '.') cc[i] = cand(i);
}
};
for (int i = 0; i < (int)R.size(); i++) cc[i] = cand(i);
function<bool(int)> dfs = [&](int filled) {
if (filled == (int)R.size()) return true;
int best = -1, bc = 10;
for (int i = 0; i < (int)R.size(); i++) {
if (board[R[i]][C[i]] == '.' && cc[i] < bc) {
bc = cc[i]; best = i;
if (!bc) return false;
if (bc < 2) break;
}
}
int r = R[best], c = C[best], b = (r / 3) * 3 + c / 3;
int mask = (~(row[r] | col[c] | box[b])) & 0x1ff;
while (mask) {
int pick = mask & -mask, d = __builtin_ctz(pick);
board[r][c] = d + '1'; row[r] |= pick; col[c] |= pick; box[b] |= pick;
recalc();
if (dfs(filled + 1)) return true;
board[r][c] = '.'; row[r] ^= pick; col[c] ^= pick; box[b] ^= pick;
recalc();
mask &= mask - 1;
}
return false;
};
dfs(0);
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
Steps of Kosaraju's Algorithm:
1. Perform a Depth First Search (DFS) on the original graph and store the nodes in a stack based on their finish times.
2. Reverse the graph by transposing its adjacency matrix (reverse all edges).
3. Perform DFS on the transposed graph in the order of nodes stored in the stack.
4. Each DFS traversal on the transposed graph gives a strongly connected component (SCC).
Uses of Kosaraju's Algorithm:
- To find strongly connected components (SCCs) in a directed graph.
- SCCs are useful in understanding the modular structure of graphs, deadlock detection, and other graph-related problems.
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MAX 1000

typedef struct Stack {
int data[MAX];
int top;
} Stack;

void initStack(Stack* stack) {
stack->top = -1;
}

void push(Stack* stack, int value) {
if (stack->top < MAX - 1) {
stack->data[++stack->top] = value;
}
}

int pop(Stack* stack) {
if (stack->top >= 0) {
return stack->data[stack->top--];
}
return -1;
}

bool isEmpty(Stack* stack) {
return stack->top == -1;
}

void dfs(int node, bool visited[], int adj[][MAX], int n, Stack* stack) {
visited[node] = true;
for (int i = 0; i < n; i++) {
if (adj[node][i] && !visited[i]) {
dfs(i, visited, adj, n, stack);
}
}
push(stack, node);
}

void dfsTranspose(int node, bool visited[], int transpose[][MAX], int n) {
visited[node] = true;
printf("%d ", node);
for (int i = 0; i < n; i++) {
if (transpose[node][i] && !visited[i]) {
dfsTranspose(i, visited, transpose, n);
}
}
}

void kosaraju(int adj[][MAX], int n) {
Stack stack;
initStack(&stack);
bool visited[MAX] = { false };
for (int i = 0; i < n; i++) {
if (!visited[i]) {
dfs(i, visited, adj, n, &stack);
}
}
int transpose[MAX][MAX] = { 0 };
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
transpose[j][i] = adj[i][j];
}
}
for (int i = 0; i < n; i++) visited[i] = false;
printf("Strongly Connected Components:\n");
while (!isEmpty(&stack)) {
int node = pop(&stack);
if (!visited[node]) {
dfsTranspose(node, visited, transpose, n);
printf("\n");
}
}
}

int main() {
int n, e;
printf("Enter the number of vertices: ");
scanf("%d", &n);
printf("Enter the number of edges: ");
scanf("%d", &e);
int adj[MAX][MAX] = { 0 };
printf("Enter the edges (u v):\n");
for (int i = 0; i < e; i++) {
int u, v;
scanf("%d %d", &u, &v);
adj[u][v] = 1;
}
kosaraju(adj, n);
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include <iostream>
using namespace std;

#define MAX 1000 // Maximum size of the queue

class Queue {
private:
int front, rear, size;
int arr[MAX]; // Queue array

public:
// Constructor to initialize the queue
Queue() {
front = 0;
rear = -1;
size = 0;
}

// Function to check if the queue is empty
bool isEmpty() {
return size == 0;
}

// Function to check if the queue is full
bool isFull() {
return size == MAX;
}

// Function to add an element to the queue
bool enqueue(int value) {
if (isFull()) {
cout << "Queue Overflow\n";
return false;
}
rear = (rear + 1) % MAX; // Circular increment
arr[rear] = value;
size++;
return true;
}

// Function to remove an element from the queue
int dequeue() {
if (isEmpty()) {
cout << "Queue Underflow\n";
return -1;
}
int value = arr[front];
front = (front + 1) % MAX; // Circular increment
size--;
return value;
}

// Function to get the front element of the queue
int getFront() {
if (isEmpty()) {
cout << "Queue is Empty\n";
return -1;
}
return arr[front];
}

// Function to get the rear element of the queue
int getRear() {
if (isEmpty()) {
cout << "Queue is Empty\n";
return -1;
}
return arr[rear];
}

// Function to display all elements in the queue
void display() {
if (isEmpty()) {
cout << "Queue is Empty\n";
return;
}
cout << "Queue elements are: ";
for (int i = 0; i < size; i++) {
cout << arr[(front + i) % MAX] << " ";
}
cout << endl;
}
};

int main() {
Queue q;

// Demonstrating queue operations
q.enqueue(10);
q.enqueue(20);
q.enqueue(30);

cout << "Front element is: " << q.getFront() << endl;
cout << "Rear element is: " << q.getRear() << endl;

q.display();

cout << "Dequeued element: " << q.dequeue() << endl;

q.display();

if (q.isEmpty()) {
cout << "Queue is empty\n";
} else {
cout << "Queue is not empty\n";
}

return 0;
}
Loading

0 comments on commit fdcfa1a

Please sign in to comment.