Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Problem — Find Number of Ways to Reach the K-th Stair - Hard Problem

## Problem Summary

You are given a non-negative integer `k`.
There is an infinite staircase with the lowest stair numbered `0`.

Suppose ,Alice starts on stair **1** with an initial `jump = 0`.
She wants to reach stair **k** using the following two operations:

1. **Go Down:**
- Move from stair `i` → `i - 1`.
- ⚠️ Cannot be used **consecutively** or when `i = 0`.

2. **Go Up:**
- Move from stair `i` → `i + 2^jump`.
- After that, set `jump = jump + 1`.

Return the total **number of ways** Alice can reach stair `k`.

---

## Key Observations to be Noted

- Movement depends not only on **position** but also on the **current jump value**.
- Since down moves cannot be consecutive, we also need to track the **last move** type.
- Therefore, each *state* is described by **three parameters**.

---

## DP State Definition

Let
```
dp[i][jump][prevDown] = number of ways to reach stair i
with current jump = jump
and previous move was 'down' or not.
```

Where:
- `i` → current stair number
- `jump` → current jump value
- `prevDown` → 0 if previous move was up, 1 if previous move was down

---
## DP Transitions
1. **Go Up**
```
nextStair = i + 2^jump
dp[nextStair][jump + 1][0] += dp[i][jump][prevDown]
```

2. **Go Down** (only if previous move was not down)
```
if prevDown == 0 and i > 0:
dp[i - 1][jump][1] += dp[i][jump][prevDown]
```

---

## Base Case
```
dp[1][0][0] = 1 # Alice starts on stair 1 with jump = 0, last move not down
```
for solving this problem, i have used the recursion with memoization..
---

## Type and Category
| Aspect | Type |
|----------------------|--------------------------------------------------------------|
| **DP Dimension** | 3D DP (`position`, `jump`, `prevDown`) |
| **Category** | State-Transition DP / Simulation DP |
| **Pattern Type** | DP with constrained transitions |
| **Related Problems** | Frog Jump , Number of Ways to Reach Target (LC 2585) |

---

## ⏱️ Time and Space Complexity
Let `maxJump` ≈ `log2(k)` (since jump grows exponentially).

| Complexity | Value |
|-------------|--------------|
| **Time** | O(k * log k) |
| **Space** | O(k * log k) |

---
## 🧩 Example
### Input
```
k = 3
```
### Possible Sequences
1. **Start(1, jump=0)** → Up → `(3, jump=1)` ✅
→ Alice reached 3 directly.

2. **Start(1)** → Up → `(3)` → Down → `(2)` → Up → `(4)` → Down → `(3)` ✅
→ Reached 3 again via multiple steps.

Hence, total ways = 2.
---

## 📘 Summary

| Concept | Description |
|--------------------|---------------------------------------------------------|
| **Problem Type** | DP with movement and state constraints |
| **DP Dimensions** | 3 (position, jump, previous move) |
| **Main Challenge** | Non-consecutive down restriction & exponential up jumps |
| **Approach** | State-transition DP |
| **Complexity** | O(k * log k) |

---
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include<bits/stdc++.h>
using namespace std;

class Solution {
public:
int waysToReachStair(int k)
{
// Variable to store total number of ways to reach stair k
long num_ways = 0;
// Loop over possible number of "up" jumps covering all cases for combination.
for (int i = 0; i <= 31; i++)
{
// After i jumps, total up moves = i + 1
int num_jumps = i + 1;
long long stairs_covered_back = (1LL << i) - k;

if (0 > stairs_covered_back || i + 1 < stairs_covered_back)
continue;
// Now we need to count number of valid sequences of "up" and "down" operations that result in total displacement
// among total possible move slots. now Compute nCr using its formula.
long long ways = 1;
for (int j = 1; j <= stairs_covered_back; j++)
{
// Multiplying in iterative form to avoid factorial overflow
ways *= (num_jumps - j + 1);
ways = ways / j;
}
// Add to total number of ways
num_ways += ways;
}
return (int)num_ways;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
class Solution
{
HashMap<String, Integer> mp;
long[] power;
int K;

int solve(int i, int jump, int canGoBack)
{
if (i > K + 1)
return 0;

String key = i + "_" + jump + "_" + canGoBack;

if (mp.containsKey(key))
return mp.get(key);

int count = 0;

if (i == K) {
count++;
}

if (canGoBack == 1) {
count += solve(i - 1, jump, 0);
}

count += solve(i + (int) power[jump], jump + 1, 1);

mp.put(key, count);
return count;
}

public int waysToReachStair(int k) {
mp = new HashMap<>();
power = new long[33];
K = k;

for (int i = 0; i < 33; ++i) {
power[i] = (long) Math.pow(2, i);
}

return solve(1, 0, 1);
}
}
51 changes: 51 additions & 0 deletions Matrix/Kth Smallest element in table/Markdown.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Problem— Kth Smallest Number in Multiplication Table

## 📄 Problem Statement

You are given two positive integers `m` and `n`, which define an `m × n` multiplication table: the value at cell `(i, j)` (1-indexed) is `i * j`.

Given a positive integer `k`, return the k-th smallest number in this multiplication table (when all the `m × n` values are written in a sorted order, counting duplicates).

### Constraints / Details

- `m, n` can be up to **3 × 10⁴**
- `k` can be up to **10⁹**
- The multiplication table has **m * n** entries (potentially up to ∼9×10⁸)
- Sorting all elements explicitly would be computationally expensive or infeasible for large sizes

---

## 🧠 Key Insights & Approach

1. **Monotonicity & counting**
- In any sorted list, the k-th smallest element `x` is such that **exactly `k` values ≤ `x`** in the table.
- For a candidate value `X`, you can **count how many table entries ≤ `X`** by summing, for each row `i` (from 1 to `m`),
`min(n, floor(X / i))`.
- Use that count to guide a **binary search** over possible values of `X`.

2. **Search space**
- The **smallest** possible value is `1 * 1 = 1`.
- The **largest** possible value is `m * n` (i.e. the bottom-right corner of the table).
- Use binary search between 1 and `m * n` (or between 1 and `m * n`, or max possible product) to find the smallest `X` such that **count(≤ X) ≥ k**.

3. **Correctness & termination**
- Because counting function is non-decreasing in `X`, binary search will home in on the correct threshold.
- The final `X` found is the **k-th smallest**.

---

## ✅ Example Cases

| Example | Input | Output | Explanation |
|-------- |-------|--------|-------------|
| 1 | `m = 3`, `n = 3`, `k = 5` | `3` | The 3×3 table is: 1,2,3; 2,4,6; 3,6,9 → sorted: 1,2,2,3,3,4,6,6,9 → the 5th element is 3 |
| 2 | `m = 2`, `n = 3`, `k = 6` | `6` | The table is: 1,2,3; 2,4,6 → sorted: 1,2,2,3,4,6 → 6 is the 6th element |

---

## ⚙️ Time & Space Complexity

| Metric | Complexity |
|---------- |-------------------------|
| **Time** | O((m + n) · log(m · n)) |
| **Space** | O(1) |
41 changes: 41 additions & 0 deletions Matrix/Kth Smallest element in table/kth_smallest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include<bits/stdc++.h>
using namespace std;
class Solution
{
public:
int findKthNumber(int m, int n, int k)
{
// Binary search on the answer range [1, m*n]
int left = 1;
int right = m * n;

while (left < right)
{
// Calculate middle value
int mid = left + (right - left) / 2;

// Count how many numbers in the multiplication table are <= mid
int count = 0;
for (int row = 1; row <= m; ++row)
{
// For each row i, elements are: i*1, i*2, ..., i*n
// Number of elements <= mid in row i is min(mid/i, n)
count += std::min(mid / row, n);
}

// If count >= k, the kth smallest number is at most mid
if (count >= k)
{
right = mid;
}

else
{
// Otherwise, the kth smallest number is greater than mid
left = mid + 1;
}
}
// left == right, which is the kth smallest number
return left;
}
};
36 changes: 36 additions & 0 deletions Matrix/Kth Smallest element in table/kth_smallest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
class Solution
{
public int findKthNumber(int m, int n, int k) {
// Initialize binary search range
// Minimum possible value is 1 (1*1), maximum is m*n
int left = 1;
int right = m * n;

// Binary search for the kth smallest number
while (left < right)
{
// Calculate middle value using unsigned right shift to avoid overflow
int mid = (left + right) >>> 1;

// Count how many numbers in the multiplication table are <= mid
int count = 0;
for (int row = 1; row <= m; row++) {
// For each row i, elements are: i*1, i*2, ..., i*n
// Count of elements <= mid in row i is min(mid/i, n)
count += Math.min(mid / row, n);
}

// Adjust search range based on count
if (count >= k) {
// If count >= k, the kth number is at most mid
right = mid;
} else {
// If count < k, the kth number must be greater than mid
left = mid + 1;
}
}

// When left == right, we've found the kth smallest number
return left;
}
}