Tuesday, May 27, 2025

LeetCode 154. Find Minimum in Rotated Sorted Array II

https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/description/

Given the sorted rotated array nums that may contain duplicates, return the minimum element of this array.

You must decrease the overall operation steps as much as possible.


Example 1:

Input: nums = [1,3,5]

Output: 1


Example 2:

Input: nums = [2,2,2,0,1]

Output: 0

 

Constraints:

n == nums.length

1 <= n <= 5000

-5000 <= nums[i] <= 5000

nums is sorted and rotated between 1 and n times.


package LeetCode.binarySearch;

public class LT154_SearchInRotatedSortedArray_duplicates {

public static void main(String[] args) {
int[] arr = {1};

System.out.println(findMin(arr));
// TC: O(log n) in best/average case, O(n) in worst case due to duplicates
// SC: O(1)
}

public static int findMin(int[] nums) {
int low = 0, high = nums.length - 1; // SC: O(1), initializing variables

int min = Integer.MAX_VALUE; // SC: O(1), auxiliary variable to track min
while (low <= high) { // TC: O(log n) best/avg, O(n) worst when duplicates reduce one by one
int mid = low + (high - low) / 2; // SC: O(1)

if (nums[low] < nums[high]) { // TC: O(1), check if already sorted
return Integer.min(nums[low], min); // SC: O(1)
}

if (nums[low] == nums[mid] && nums[mid] == nums[high]) { // TC: O(1)
min = Integer.min(nums[low], min); // SC: O(1)
low++; // TC: O(1)
high--; // TC: O(1)
}
// left half is sorted
else if (nums[low] <= nums[mid]) { // TC: O(1)
min = Integer.min(nums[low], min); // SC: O(1)
low = mid + 1; // TC: O(1)
} else {
min = Integer.min(nums[mid], min); // SC: O(1)
high = mid - 1; // TC: O(1)
}
}

return min; // SC: O(1)
}
}


Here’s the Time and Space Complexity of the findMin function in a clear table format:

CaseTime ComplexitySpace Complexity
BestO(1)O(1)
AverageO(log n)O(1)
WorstO(n)O(1)

Explanation:

  • Best Case: The array is already sorted (nums[low] < nums[high]).

  • Average Case: Standard binary search logic with occasional duplicates.

  • Worst Case: All or many elements are duplicates, causing the loop to degrade into linear time.

Monday, May 26, 2025

LeetCode 153. Find Minimum in Rotated Sorted Array I

https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/description/

Given the sorted rotated array nums of unique elements, return the minimum element of this array.

You must write an algorithm that runs in O(log n) time.


 Example 1:

Input: nums = [3,4,5,1,2]

Output: 1

Explanation: The original array was [1,2,3,4,5] rotated 3 times.


Example 2:

Input: nums = [4,5,6,7,0,1,2]

Output: 0

Explanation: The original array was [0,1,2,4,5,6,7] and it was rotated 4 times.


Example 3:

Input: nums = [11,13,15,17]

Output: 11

Explanation: The original array was [11,13,15,17] and it was rotated 4 times. 

{4, 5, 6, 7, 0, 1, 2, 3}
{7, 8, 0, 1, 2, 3, 4, 5, 6}
{4, 5, 1, 2, 3}


package LeetCode.binarySearch;

public class LT153_SearchInRotatedSortedArray3 {

public static void main(String[] args) {
int[] arr = new int[]{4, 5, 6, 7, 0, 1, 2, 3};
arr = new int[]{4, 5, 1, 2, 3};
arr = new int[]{4, 5, 6, 0, 1, 2};

System.out.println(search(arr));

}

public static int search(int[] nums) {
int low = 0; // O(1) time & space
int high = nums.length - 1; // O(1) time & space
int min = Integer.MAX_VALUE; // O(1) time & space

// Loop will run at most O(log n) times since we halve the search space each iteration
while (low <= high) { // O(log n) time
int mid = low + (high - low) / 2; // O(1) time & space

// if search space is already sorted
// then always arr[low] will be smaller
if (nums[low] <= nums[high]) {
min = Math.min(min, nums[low]);
break;
}

// Left half is sorted
if (nums[low] <= nums[mid]) { // O(1) time
// get minimum
min = Math.min(min, nums[low]); // O(1) time

// eliminate left half
low = mid + 1; // O(1) time & space
}
// Right half is sorted
else {
// get minimum
min = Math.min(min, nums[mid]); // O(1) time

// eliminate right half
high = mid - 1; // O(1) time & space
}
}

return min; // O(1) time & space
}
}

Time Complexity (TC):
Best Case: O(1) — minimum found immediately
Average Case: O(log n) — binary search halving the array
Worst Case: O(log n) — rotated array causes full binary search traversal

Space Complexity (SC):
Best/Average/Worst Case: O(1) — only constant extra space used

LeetCode 81. Search in Rotated Sorted Array II

https://leetcode.com/problems/search-in-rotated-sorted-array-ii/description/ 

Given the array nums after the rotation and an integer target, return true if target is in nums, or false if it is not in nums.


You must decrease the overall operation steps as much as possible.


 Example 1:

Input: nums = [2,5,6,0,0,1,2], target = 0

Output: true


Example 2:

Input: nums = [2,5,6,0,0,1,2], target = 3

Output: false


Example 3: EDGE CASE

Input: nums = [3,3,1,2,3,3,3], target = 1

Output: true


package LeetCode.binarySearch;

public class LT81_SearchInRotatedSortedArray2 {

public static void main(String[] args) {
int[] arr = {3, 3, 1, 2, 3, 3, 3};

int target = 0;

boolean idx = search(arr, target);
System.out.println(idx);

}

/**
* Time Complexity:
* - Best / Average Case: O(log n), due to binary search.
* - Worst Case: O(n), when duplicates force linear scan (e.g., [1,1,1,1,1,1,2,1]).
* Space Complexity: O(1), constant space used.
*/
public static boolean search(int[] nums, int target) {
int low = 0, high = nums.length - 1;

while (low <= high) {
int mid = low + (high - low) / 2;

// Check mid
if (nums[mid] == target)
return true;

// Handle duplicates on both ends
if (nums[low] == nums[mid] && nums[mid] == nums[high]) {
low++;
high--;
}
// Left half is sorted
else if (nums[low] <= nums[mid]) {
if (nums[low] <= target && target < nums[mid])
high = mid - 1;
else
low = mid + 1;
}
// Right half is sorted
else {
if (nums[mid] < target && target <= nums[high])
low = mid + 1;
else
high = mid - 1;
}
}

return false;
}

}


CaseTime ComplexitySpace ComplexityExplanation
BestO(1)O(1)Target found at the middle index in the first comparison.
AverageO(log n)O(1)Normal binary search behavior when duplicates are minimal or non-impactful.
WorstO(n)O(1)When duplicates prevent binary decision, forcing linear reduction (e.g., [1,1,1,1,2,1]).

Example: WORST CASE EG.

int[] nums = {2, 2, 2, 2, 3, 2, 2};

int target = 3;

👇 What happens during binary search:

  1. Initial State:

    low = 0, high = 6, mid = 3
    nums[mid] = 2, nums[low] = 2, nums[high] = 2
    • Since nums[low] == nums[mid] == nums[high], we can't tell which side is sorted.

    • So we do:

      low++, high--;
    • This continues, narrowing the range one step at a time, just like linear search.

  2. This repeats until we find 3 or exhaust the array.

⚠️ Why This Is Bad:

  • Because we can't divide the array in half using binary logic due to all elements being the same.

  • So we reduce low and high by 1 each time — leading to O(n) time.


LeetCode 33. Search in Rotated Sorted Array I

 https://leetcode.com/problems/search-in-rotated-sorted-array/

https://www.youtube.com/watch?v=5qGrJbHhqFs&list=PLgUwDviBIf0pMFMWuuvDNMAkoQFi-h0ZF&index=5 

Given the array nums after the possible rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.

You must write an algorithm with O(log n) runtime complexity.

 

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0

Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3

Output: -1

Example 3:

Input: nums = [1], target = 0

Output: -1

 

Constraints:

1 <= nums.length <= 5000

-104 <= nums[i] <= 104

All values of nums are unique.

nums is an ascending array that is possibly rotated.

-104 <= target <= 104



package LeetCode.binarySearch;

public class LT33_SearchInRotatedSortedArray {

public static void main(String[] args) {
int[] arr = {7, 8, 9, 1, 2, 3, 4, 5, 6};

int target = 0;

int idx = search(arr, target);
System.out.println(idx);

}

public static int search(int[] nums, int target) {
// Time Complexity: O(log n)
// Space Complexity: O(1)

int low = 0, high = nums.length - 1;

while (low <= high) {

int mid = low + (high - low) / 2;

if (nums[mid] == target)
return mid;

// LEFT HALF IS SORTED
else if (nums[low] <= nums[mid]) {

if (nums[low] <= target && target <= nums[mid])
// Target lies in the left half
high = mid - 1;
else
// Target lies in the right half
low = mid + 1;
} else {
// RIGHT HALF IS SORTED
if (nums[mid] <= target && target <= nums[high])
// Target lies in the right half
low = mid + 1;
else
// Target lies in the left half
high = mid - 1;
}
}

return -1; // Target not found
}
}


}


🔍 Summary

CaseTime ComplexitySpace Complexity
BestO(1)O(1)
AverageO(log n)O(1)
WorstO(log n)O(1)

Saturday, May 24, 2025

Any base multiplication

1. You are given a base b

2. You are given 2 numbers n1 and n2 of base b

3. You are required to multiply n1 and n2 and print the value


Input Format:

- A base b

- A number n1

- A number n2


Output:

diff of n2 & n1 in base b


Constraints:

2 <= b <= 10

0 <= n1 <= 10000

0 <= n2 <= 10000


Input: 

5

1220

31


package jan19;

public class AnyBaseMultiplication {

public static void main(String[] args) {
int n1b8 = 2156;
int n2b8 = 74;
int base = 8;

int product = getProduct(n1b8, n2b8, base); // O(d2 * d1) where d2 = digits of n2, d1 = digits of n1
System.out.println(product);
}

/**
* Time Complexity: O(d2 × d1), where d1 = number of digits in n1b8 and d2 = number of digits in n2b8
* Space Complexity: O(1) – constant extra space used (no dynamic data structures)
*/
private static int getProduct(int n1b8, int n2b8, int base) {
int finalAns = 0, power = 0;

while (n2b8 > 0) { // O(d2)
int n = n2b8 % 10;
n2b8 = n2b8 / 10;

// single digit multiplication + positional shift
int singleProduct = anyBaseMultiplicationSingleDigit(n1b8, n, base) * (int) Math.pow(10, power++);

// sum of partial product with the result so far
finalAns = getSum(finalAns, singleProduct, base); // O(d1)
}

return finalAns;
}

/**
* Multiplies a number with a single digit in any base
* Time Complexity: O(d1) – d1 = number of digits in n1b8
* Space Complexity: O(1)
*/
private static int anyBaseMultiplicationSingleDigit(int n1b8, int n, int base) {

int carry = 0, ans = 0, power = 0, remainder = 0;

while (n1b8 > 0) { // O(d1)
int a = n1b8 % 10;
n1b8 = n1b8 / 10;

int product = a * n + carry;

carry = (product >= base) ? product / base : 0;
remainder = product % base;

ans += remainder * (int) Math.pow(10, power++);
}

// Add leftover carry
ans = carry != 0 ? ans + (carry * (int) Math.pow(10, power++)) : ans;

return ans;
}

/**
* Adds two numbers in a given base
* Time Complexity: O(max(d1, d2)) – number of digits in max(n1B8, n2B8)
* Space Complexity: O(1)
*/
private static int getSum(int n1B8, int n2B8, int base) {
int carry = 0, ans = 0, power = 0;

while (n1B8 > 0 || n2B8 > 0 || carry > 0) { // O(max(d1, d2))
int a = n1B8 % 10;
int b = n2B8 % 10;
n1B8 = n1B8 / 10;
n2B8 = n2B8 / 10;

int sum = a + b + carry;
carry = sum / base;

ans += (sum % base) * (int) Math.pow(10, power++);
}

return ans;
}
}

📊 Time and Space Complexity Summary Table:

OperationTime ComplexitySpace Complexity
getProduct(n1, n2, base)O(d1 × d2)O(1)
anyBaseMultiplicationSingleDigitO(d1)O(1)
getSumO(max(d1, d2))O(1)
  • d1 = number of digits in n1b8

  • d2 = number of digits in n2b8

📊 Complexity Table

CaseTime ComplexitySpace ComplexityExplanation
BestO(d1 × d2)O(1)Even in the best case (e.g., multiplying by 0 or 1), we still iterate over digits of both numbers due to multiplication and addition logic.
AverageO(d1 × d2)O(1)Typical input: both numbers have several digits and require full traversal.
WorstO(d1 × d2)O(1)Maximum digits in both inputs. Also includes carry propagation across all digits in each addition.

 

🔍 Why O(d1 × d2)?

  • For each digit of n2 (let’s say it has d2 digits), we:

    • Multiply entire n1 (d1 digits) → O(d1)

    • Add result to final answer → O(d1) (since result grows gradually)

  • So total time: d2 × O(d1)O(d1 × d2)

🧠 Why O(1) Space?

  • Only a few integer variables are used (carry, power, ans).

  • No recursion or dynamic data structure

Any base substraction

1. You are given a base b

2. You are given 2 numbers n1 and n2 of base b

3. You are required to substract n1 from n2 and print the value


Input Format:

- A base b

- A number n1

- A number n2


Output:

diff of n2 & n1 in base b


Constraints:

2 <= b <= 10

0 <= n1 <= 256

0 <= n2 <= 256


package jan19;

public class AnyBaseSubstraction {
public static void main(String[] args) {

int n1b8 = 1212;
int n2b8 = 236;
int base = 8;

anyBaseSubstraction(n1b8, n2b8, base);
}

/**
* Time Complexity: O(d), where d = number of digits in the longer number
* Space Complexity: O(1), constant space used
*/
private static void anyBaseSubstraction(int n1b8, int n2b8, int base) {

int carryFromPrevious = 0, ans = 0, power = 0; // O(1)
while (n1b8 > 0 || n2b8 > 0) { // O(d) loop where d = number of digits

int a = n1b8 % 10; // O(1)
if (carryFromPrevious == -1)
a = a - 1; // O(1)
int b = n2b8 % 10; // O(1)

n1b8 = n1b8 / 10; // O(1)
n2b8 = n2b8 / 10; // O(1)

if (a < b) {
carryFromPrevious = -1; // O(1)
a = a + base; // O(1)
}

ans += (a - b) * (int) Math.pow(10, power++); // O(1), since power is small (integer)
}

System.out.println(ans); // O(1)
}
}


📊 Complexity Table

CaseTime ComplexitySpace ComplexityExplanation
BestO(1)O(1)If both numbers are zero or subtraction completes in one digit.
AverageO(d)O(1)Where d is the number of digits in the longer of the two numbers.
WorstO(d)O(1)When subtraction and borrow propagation continue for all digits.
💡 d is the number of digits, typically O(log₁₀(n)), but represented as O(d) to reflect per-digit operations in base conversions.

✅ Uses constant space as it stores only digits and a few integers, no extra data structures are used.

Any base addition

  1. You are given a base b

2. You are given 2 numbers of base b

3. You are required to add two numbers and print their values in base b.


Input Format:

- A base b

- A number n1

- A number n2


Output:

sum of n1 & n2 in base b


Constraints:

2 <= b <= 10

0 <= n1 <= 256

0 <= n2 <= 256



package jan19;

public class AnyBaseAddition {
public static void main(String[] args) {
int n1_b_8 = 236;
int n2_b_8 = 754;
int base = 8;

sum(n1_b_8, n2_b_8, base);
}

/**
* Adds two numbers given in a specific base and prints the result in that base.
*
* Time Complexity: O(max(d1, d2))
* - Where d1 and d2 are the number of digits in n1 and n2.
* - In each iteration, one digit from each number is processed.
*
* Space Complexity: O(1)
* - Uses a fixed amount of space regardless of input size.
*/
private static void sum(int n1B8, int n2B8, int base) {
int carry = 0, ans = 0, power = 0;

while (n1B8 > 0 || n2B8 > 0 || carry > 0) {
int a = n1B8 % 10;
int b = n2B8 % 10;
n1B8 = n1B8 / 10;
n2B8 = n2B8 / 10;

int sum = a + b + carry;
carry = sum / base;

ans += (sum % base) * (int) Math.pow(10, power++);
}

System.out.println(ans);
}
}


CaseTime ComplexitySpace ComplexityExplanation
Best CaseO(1)O(1)When both numbers are 0, only one loop iteration runs.
Average CaseO(d)O(1)Where d is the number of digits in the longer of the two numbers.
Worst CaseO(d)O(1)Carries continue through all digits, requiring processing every digit. 

💡 Note: The number of digits d in a number n is O(log₁₀(n)), so technically it's O(log₁₀(n)), but in competitive programming and base conversion contexts, we usually denote it as O(d) to reflect digit-based iterations.

 

Tuesday, May 20, 2025

First and Last Index

 Input: 

10, 20, 20, 20, 20, 20, 40, 50, 50, 60
20

Output:
1
5

package jan21;

public class FirstLastIndex {
public static void main(String[] args) {

int[] arr = {10, 20, 20, 20, 20, 20, 40, 50, 50, 60};
int data = 20;

int low = 0, high = arr.length - 1, firstIndex = -1, lastIndex = -1;

// -----------------------
// Find First Index
// -----------------------

// Time Complexity: O(log n)
// Space Complexity: O(1)
// Binary search to find first occurrence of 'data'
while (low <= high) {
int mid = low + (high - low) / 2;
if (data > arr[mid]) {
low = mid + 1;
} else if (data < arr[mid]) {
high = mid - 1;
} else {
firstIndex = mid; // potential first index found
high = mid - 1; // move left to find earlier occurrence
}
}

System.out.println(firstIndex);

// -----------------------
// Find Last Index
// -----------------------

low = 0;
high = arr.length - 1;
lastIndex = -1;

// Time Complexity: O(log n)
// Space Complexity: O(1)
// Binary search to find last occurrence of 'data'
while (low <= high) {
int mid = low + (high - low) / 2;
if (data > arr[mid]) {
low = mid + 1;
} else if (data < arr[mid]) {
high = mid - 1;
} else {
lastIndex = mid; // potential last index found
low = mid + 1; // move right to find later occurrence
}
}

System.out.println(lastIndex);
}
}

📊 Complexity Table

CaseTime ComplexitySpace ComplexityDescription
BestO(log n)O(1)Binary search immediately finds the element on first try
AverageO(log n)O(1)Standard binary search behavior, divides the array in halves
WorstO(log n)O(1)Element occurs multiple times (as in your example), so both full searches needed

Ceil & Floor

Find ceil and floor of number n in array.

Input:

array

number

Ceil is value in array which is just greater than n. If an element is equal to n exists that will be considered as ceil.

Floor is value in array which is just less than n. If an element is equal to n exists that will be considered as floor.

Assumption: array is sorted.

eg. 10 20 30 40 50 60 70 80 90 100

n = 55, ceil = 50; floor = 60

n = 40, ceil = 40; floor = 40


package jan21;

public class CeilFloor {
public static void main(String[] args) {

int[] arr = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int n = 33;

int low = 0, high = arr.length - 1;
int ceil = Integer.MAX_VALUE;
int floor = Integer.MIN_VALUE;

// Time Complexity: O(log n)
// - Binary search cuts the search space in half each time.
//
// Space Complexity: O(1)
// - Only a few variables used regardless of input size.

while (low <= high) {
int mid = low + (high - low) / 2; // O(1)
if (arr[mid] > n) {
high = mid - 1;
ceil = arr[mid]; // potential ceil found
} else if (arr[mid] < n) {
low = mid + 1;
floor = arr[mid]; // potential floor found
} else {
ceil = arr[mid]; // exact match
floor = arr[mid];
break;
}
}

System.out.println(floor);
System.out.println(ceil);
}
}

📊 Time & Space Complexity Table

CaseTime ComplexitySpace ComplexityExplanation
BestO(1)O(1)If n is found at the first mid point
AverageO(log n)O(1)Binary search divides the array in half each iteration
WorstO(log n)O(1)In worst case, full binary search needed without finding n exactly

Diagonal Traversal

 eg.  1       2       3       4 5      6       7       8 9    10    11     12 13  14   15    16 Output: 1 6 11 16 2 7 12 3 8 4  Approach:...