Divide and Conqure Cheatsheet
Divide and Conqure Cheatsheet
1
// if((mid>0 && arr[mid]>arr[mid - 1]) || (mid<arr.length - 1 {
&& arr[mid]>arr[mid+1])) int k = low, i = low, j = mid + 1;
{
return mid; // while there are elements in the left and
} right runs
else if(mid< arr.length - 1 && arr[mid+1]>arr[mid]) while (i <= mid && j <= high)
{ {
return findPeak(arr,mid+1,end); if (arr[i] <= arr[j]) {
} aux[k++] = arr[i++];
else }
{ else {
return findPeak(arr,start,mid-1); aux[k++] = arr[j++];
} }
} }
public static int[] findPeak2d(int[][] arr)
{ // copy remaining elements
int stcol=0; while (i <= mid) {
int endcol=arr[0].length - 1; aux[k++] = arr[i++];
}
while(stcol<=endcol)
{ // No need to copy the second half
int mid_col = stcol+(endcol-stcol)/2; (since the remaining items
int max = 0; // are already in their correct position in
int max_index = 0; the auxiliary array)
for(int i=0;i<arr.length;i++)
{ // copy back to the original array to
if(arr[i][mid_col] > max) { reflect sorted order
max = arr[i][mid_col]; for (i = low; i <= high; i++) {
max_index = i; arr[i] = aux[i];
} }
}
}
// Sort array `arr[low…high]` using auxiliary array
boolean valid_left = mid_col > stcol && `aux`
(arr[max_index][mid_col - 1] > arr[max_index][mid_col]); public static void mergesort(int[] arr, int[] aux, int
boolean valid_right = mid_col < endcol && low, int high)
(arr[max_index][mid_col + 1] > arr[max_index][mid_col]); {
// base case
if(!valid_left && !valid_right) if (high <= low) { // if run
return new int[] { max_index, mid_col }; size <= 1
else if (valid_left) { return;
endcol = mid_col - 1; }
}
else { // find midpoint
stcol = mid_col + 1; int mid = (low + ((high - low) >> 1));
}
} // recursively split runs into two halves
return new int[] { -1, -1 }; until run size <= 1,
} // then merge them and return up the
public static void printMatrix(int[][] matrix) { call chain
for (int[] row : matrix) {
for (int element : row) { mergesort(arr, aux, low, mid);
System.out.print(element + " "); // split/merge left half
} mergesort(arr, aux, mid + 1, high);
System.out.println(); // split/merge right half
}
} merge(arr, aux, low, mid, high);
} // merge the two half runs
}
2
// Iteratively sort subarray `A[low…high]` using a
System.out.println("MergeSort Fails!!"); temporary array
return false; public static void mergesort(int[] A)
} {
prev = arr[i]; int low = 0;
} int high = A.length - 1;
3
// equal elements can go either way }
int pIndex = start;
public int getX() { return x; }
// each time we find an element less than or equal to the public int getY() { return y; }
pivot, }
// `pIndex` is incremented, and that element would be
placed class Main
// before the pivot. {
for (int i = start; i < end; i++) public static void swap (int[] nums, int i, int j)
{ {
if (a[i] <= pivot) int temp = nums[i];
{ nums[i] = nums[j];
swap(a, i, pIndex); nums[j] = temp;
pIndex++; }
}
} // Partition routine using the Dutch national flag
algorithm
// swap `pIndex` with pivot public static Pair partition(int[] nums, int start, int
swap(a, end, pIndex); end)
{
// return `pIndex` (index of the pivot element) int mid = start;
return pIndex; int pivot = nums[end];
}
while (mid <= end)
// Quicksort routine {
public static void quicksort(int[] a, int start, int end) if (nums[mid] < pivot)
{ {
// base condition swap(nums, start,
if (start >= end) { mid);
return; ++start;
} ++mid;
}
// rearrange elements across pivot else if (nums[mid] > pivot)
int pivot = partition(a, start, end); {
swap(nums, mid,
// recur on subarray containing elements less than the end);
pivot --end;
quicksort(a, start, pivot - 1); }
else {
// recur on subarray containing elements more than the ++mid;
pivot }
quicksort(a, pivot + 1, end); }
}
// nums[start … mid-1] contains all
// Java implementation of the Quicksort algorithm occurrences of a pivot
public static void main(String[] args) return new Pair(start - 1, mid);
{ }
int[] a = { 9, -3, 5, 2, 6, 8, -6, 1, 3 };
// 3–way Quicksort routine
quicksort(a, 0, a.length - 1); public static void quicksort(int[] nums, int start, int
end)
// print the sorted array {
System.out.println(Arrays.toString(a)); // base condition for 0 or 1 elements
} if (start >= end) {
} return;
}
QS Dutch
// rearrange elements across pivot using
import java.util.Arrays; the Dutch national flag algorithm
Pair pivot = partition(nums, start, end);
// A simple pair class in Java
class Pair // recur on the subarray containing
{ elements that are less than the pivot
private int x; quicksort(nums, start, pivot.getX());
private int y;
// recur on the subarray containing
Pair(int x, int y) elements that are more than the pivot
{ quicksort(nums, pivot.getY(), end);
this.x = x; }
this.y = y;
4
public static void main(String[] args) // find midpoint
{ int mid = (low + ((high - low) >> 1));
int[] nums = { 2, 6, 5, 2, 6, 8, 6, 1, 2, 6 }; int inversionCount = 0;
5
} {
} private final int x;
private final int y;
// copy positive elements from the left
subarray Pair(int x, int y)
for (int i = low; i <= mid; i++) {
{ this.x = x;
if (arr[i] >= 0) { this.y = y;
aux[k++] = arr[i]; }
}
} public int getX() { return x; }
public int getY() { return y; }
// copy positive elements from the right }
subarray
for (int j = mid + 1; j <= high; j++) class Main
{ {
if (arr[j] >= 0) { public static void swap (int[] arr, int i, int j)
aux[k++] = arr[j]; {
} int temp = arr[i];
} arr[i] = arr[j];
arr[j] = temp;
// copy back to the original array to }
reflect sorted order
for (int i = low; i <= high; i++) { public static int partition(int a[], int start, int end)
arr[i] = aux[i]; {
} // Pick the rightmost element as a pivot
} from the array
int pivot = a[end];
// Segregate positive and negative integers using a
mergesort-like routine // elements less than the pivot will go to
public static void partition(int[] arr, int[] aux, int low, the left of `pIndex`
int high) // elements more than the pivot will go to
{ the right of `pIndex`
// Base case // equal elements can go either way
if (high <= low) { int pIndex = start;
return;
} // each time we find an element less
than or equal to the pivot,
// find midpoint // `pIndex` is incremented, and that
int mid = (low + ((high - low) >> 1)); element would be placed
// before the pivot.
partition(arr, aux, low, mid); for (int i = start; i < end; i++)
// split/merge left half {
partition(arr, aux, mid + 1, high); if (a[i] <= pivot)
// split/merge right half {
swap(a, i, pIndex);
merge(arr, aux, low, mid, high); pIndex++;
// join the two half runs }
} }
6
// push the start and end index of the // compares it with the target
array into the stack
stack.push(new Pair(start, end)); int mid = (left + right) / 2;
Binary Search O(log2n) Find the number of rotations in a circularly sorted array
O(log(n))
class Main class Main
{ {
// Recursive implementation of the binary search // Function to find the total number of times the array is
algorithm to return rotated
// the position of `target` in subarray public static int findRotationCount(int[] nums)
nums[left…right] {
public static int binarySearch(int[] nums, int left, int // search space is nums[left…right]
right, int target) int left = 0;
{ int right = nums.length - 1;
// Base condition (search space is
exhausted) // loop till the search space is exhausted
if (left > right) { while (left <= right)
return -1; {
} // if the search space is already sorted, we have
// found the minimum element (at index `left`)
// find the mid-value in the search space if (nums[left] <= nums[right]) {
and return left;
7
} int mid = (left + right) / 2;
8
else { System.out.println("The first
System.out.println("Element occurrence of element " + target +
not found in the array");
} " is located at index " + index);
} }
} else {
System.out.println("Element
Find the first of a given number in a sorted array not found in the array");
O(log(n)) }
}
class Main }
{
// Function to find the first occurrence of a given Find the last occurrence of a given number in a sorted
number array
// in a sorted integer array O(log(n))
public static int findFirstOccurrence(int[] nums, int class Main
target) {
{ // Function to find the last occurrence of a given
// search space is nums[left…right] number
int left = 0; // in a sorted integer array
int right = nums.length - 1; public static int findLastOccurrence(int[] nums, int
target)
// initialize the result by -1 {
int result = -1; // search space is nums[left…right]
int left = 0;
// loop till the search space is exhausted int right = nums.length - 1;
while (left <= right)
{ // initialize the result by -1
// find the mid-value in the int result = -1;
search space and compares it with the target
int mid = (left + right) / 2; // loop till the search space is exhausted
while (left <= right)
// if the target is located, {
update the result and // find the mid-value in the
// search towards the left search space and compares it with the target
(lower indices) int mid = (left + right) / 2;
if (target == nums[mid])
{ // if the target is located,
result = mid; update the result and
right = mid - 1; // search towards the right
} (higher indices)
if (target == nums[mid])
// if the target is less than the {
middle element, discard the right half result = mid;
else if (target < nums[mid]) { left = mid + 1;
right = mid - 1; }
}
// if the target is less than the
// if the target is more than the middle element, discard the right half
middle element, discard the left half else if (target < nums[mid]) {
else { right = mid - 1;
left = mid + 1; }
}
} // if the target is more than the
middle element, discard the left half
// return the leftmost index, or -1 if the else {
element is not found left = mid + 1;
return result; }
} }
public static void main(String[] args) // return the leftmost index, or -1 if the
{ element is not found
int[] nums = {2, 5, 5, 5, 6, 6, 8, 9, 9, 9}; return result;
int target = 5; }
9
int index = findLastOccurrence(nums, // if the target is more than the
target); middle element, discard the left half
else {
if (index != -1) left = mid + 1;
{ }
System.out.println("The last }
occurrence of element " + target +
" is // return the found index or -1 if the
located at index " + index); element is not found
} return result;
else { }
System.out.println("Element
not found in the array"); public static void main(String[] args)
} {
} int[] nums = {2, 5, 5, 5, 6, 6, 8, 9, 9, 9};
} int target = 5;
Count occurrences of a number in a sorted array with // pass true for the first occurrence
duplicates int first = binarySearch(nums, target,
O(log(n)) true);
class Main
{ // pass false for the last occurrence
// Function to find the first or last occurrence of a int last = binarySearch(nums, target,
given number in false);
// a sorted integer array. If `searchFirst` is true,
return the int count = last - first + 1;
// first occurrence of the number; otherwise, return
its last occurrence. if (first != -1) {
public static int binarySearch(int[] nums, int target, System.out.println("Element "
boolean searchFirst) + target + " occurs " + count + " times");
{ }
// search space is nums[left…right] else {
int left = 0; System.out.println("Element
int right = nums.length - 1; not found in the array");
}
// initialize the result by -1 }
int result = -1; }
// loop till the search space is exhausted Find the smallest missing element from a sorted array
while (left <= right) O(log(n))
{ class Main
// find the mid-value in the {
search space and compares it with the target // Function to find the smallest missing element in a sorted
int mid = (left + right) / 2; // array of distinct non-negative integers
public static int findSmallestMissing(int[] nums, int left, int
// if the target is found, update right)
the result {
if (target == nums[mid]) // base condition
{ if (left > right) {
result = mid; return left;
}
// go on searching
towards the left (lower indices) int mid = left + (right - left) / 2;
if (searchFirst) {
right = // if the mid-index matches with its value, then the
mid - 1; mismatch
} // lies on the right half
// go on searching if (nums[mid] == mid) {
towards the right (higher indices) return findSmallestMissing(nums, mid + 1, right);
else { }
left = mid else {
+ 1; // mismatch lies on the left half
} return findSmallestMissing(nums, left, mid - 1);
} }
}
// if the target is less than the
middle element, discard the right half public static void main(String[] args)
else if (target < nums[mid]) { {
right = mid - 1; int[] nums = { 0, 1, 2, 3, 4, 5, 6 };
}
10
int left = 0, right = nums.length - 1; public static int findFloor(int[] nums, int left, int
System.out.println("The smallest missing element is " right, int x)
+ findSmallestMissing(nums, left, right)); {
} // search space is nums[left…right]
}
// base case
Find floor and ceil of a number in a sorted integer array if (nums.length == 0) {
O(log(n)) return -1;
class Main }
{
// Function to find the ceiling of `x` in a sorted array // if `x` is less than the lowest element in
nums[low…high]. search
// i.e., the smallest integer greater than or equal to // space, its floor doesn't exist
`x` if (x < nums[left]) {
public static int findCeiling(int[] nums, int left, int return -1;
right, int x) }
{
// search space is nums[left…right] // if `x` is more than equal to the highest
element in
// base case // the search space, it is the floor
if (nums.length == 0) { if (x >= nums[right]) {
return -1; return nums[right];
} }
// if `x` is less than equal to the lowest // find the middle index
element in search int mid = (left + right) / 2;
// space, the lowest element is the
ceiling // this check is placed to handle infinite
if (x <= nums[left]) { loop for
return nums[left]; // a call to `findFloor(nums, mid, right, x)`
} if (mid == left) {
return nums[left];
// if `x` is more than the highest element }
in the search space,
// its ceiling doesn't exist // if `x` is equal to the middle element, it
if (x > nums[right]) { is the floor
return -1; if (nums[mid] == x) {
} return nums[mid];
}
// find the middle index
int mid = (left + right) / 2; // if `x` is more than the middle element,
the floor exists in the right
// if `x` is equal to the middle element, it // subarray nums[mid…right](Note –
is the ceiling middle element can also be the floor)
if (nums[mid] == x) { else if (nums[mid] < x) {
return nums[mid]; return findFloor(nums, mid,
} right, x);
}
// if `x` is more than the middle element,
the ceiling exists in the right // if `x` is less than the middle element,
// subarray nums[mid+1…right] the floor exists in the left
else if (nums[mid] < x) { // subarray nums[left…mid-1]
return findCeiling(nums, mid + else {
1, right, x); return findFloor(nums, left,
} mid - 1, x);
}
// if `x` is less than the middle element, }
the ceiling exists in the left
// subarray nums[left…mid] (Note – public static void main(String[] args)
middle element can also be ceiling) {
else { int[] nums = { 1, 4, 6, 8, 9 };
return findCeiling(nums, left,
mid, x); for (int i = 0; i <= 10; i++)
} {
} System.out.printf("Number
%2d —> ceiling is %2d, floor is %2d\n", i,
// Function to find the floor of `x` in a sorted array
nums[left…right]. findCeiling(nums, 0, nums.length - 1, i),
// i.e., the largest integer less than or equal to `x`
findFloor(nums, 0, nums.length - 1, i));
11
} int target = 5;
}
} int index = searchElement(nums,
target);
Search in a nearly sorted array in logarithmic time
O(log(n)) if (index != -1) {
class Main System.out.println("Element "
{ + target + " found at index " + index);
// Function to search an element `target` in a }
nearly sorted array `nums` else {
public static int searchElement(int[] nums, int System.out.println("Element
target) not found in the array");
{ }
// search space is nums[left…right] }
int left = 0; }
int right = nums.length - 1;
Find the number of 1’s in a sorted binary array
// loop till the search space is exhausted O(log(n))
while (left <= right) class Main
{ {
// find middle index `mid` and // Function to find the total number of 1's in a
compare nums[mid-1], nums[mid], and nums[mid+1] sorted binary array
// with the target number public static int count(int[] nums, int left, int right)
int mid = (left + right) / 2; {
// base case
// return `mid` if the middle if (nums == null || nums.length == 0) {
element is equal to the target number return 0;
if (nums[mid] == target) { }
return mid;
} // if the last array element is 0, no 1's
can
// return `mid-1` if nums[mid-1] // be present since it is sorted
is equal to target number if (nums[right] == 0) {
else if (mid - 1 >= left && return 0;
nums[mid - 1] == target) { }
return mid - 1;
} // if the first array element is 1, all its
elements
// return `mid+1` if // are ones only since it is sorted
nums[mid+1] is equal to target number if (nums[left] == 1) {
else if (mid + 1 <= right && return (right - left + 1);
nums[mid + 1] == target) { }
return mid + 1;
} // divide the array into left and right
subarray and recur
// if the middle element is less int mid = (left + right) / 2;
than the target number, return count(nums, left, mid) +
// reduce search space to the count(nums, mid + 1, right);
right subarray nums[mid+2…right] }
else if (target > nums[mid]) {
left = mid + 2; public static void main(String[] args)
} {
int[] nums = { 0, 0, 0, 0, 1, 1, 1 };
// if the middle element is
greater than the target number, System.out.println("The total number of
// reduce search space to the 1's present is "
right subarray nums[left…mid-2]
else { + count(nums, 0, nums.length
right = mid - 2; - 1));
} }
} }
// invalid input or number is not present Find the peak element in an array
in the array O(log(n))
return -1;
} class Main
{
public static void main(String[] args) // Recursive function to find the peak element in an
{ array
int[] nums = { 2, 1, 3, 5, 4, 7, 6, 8, 9 };
12
public static int findPeakElement(int[] nums, int
left, int right) // Find maximum subarray sum for the
{ left subarray,
// find the middle element. To avoid // including the middle element
overflow, use mid = low + (high - low) / 2 int leftMax = Integer.MIN_VALUE;
int mid = (left + right) / 2; int sum = 0;
for (int i = mid; i >= left; i--)
// check if the middle element is greater {
than its neighbors sum += nums[i];
if ((mid == 0 || nums[mid - 1] <= if (sum > leftMax) {
nums[mid]) && leftMax = sum;
(mid == }
nums.length - 1 || nums[mid + 1] <= nums[mid])) { }
return mid;
} // Find maximum subarray sum for the
right subarray,
// If the left neighbor of `mid` is greater // excluding the middle element
than the middle element, int rightMax = Integer.MIN_VALUE;
// find the peak recursively in the left sum = 0; // reset sum to 0
subarray for (int i = mid + 1; i <= right; i++)
if (mid - 1 >= 0 && nums[mid - 1] > {
nums[mid]) { sum += nums[i];
return findPeakElement(nums, if (sum > rightMax) {
left, mid - 1); rightMax = sum;
} }
}
// If the right neighbor of `mid` is greater
than the middle element, // Recursively find the maximum
// find the peak recursively in the right subarray sum for the left
subarray // and right subarray, and take maximum
return findPeakElement(nums, mid + 1, int maxLeftRight =
right); Integer.max(findMaximumSum(nums, left, mid),
}
findMaximumSum(nums, mid
public static int findPeakElement(int[] nums) + 1, right));
{
// base case // return the maximum of the three
if (nums == null || nums.length == 0) { return Integer.max(maxLeftRight,
System.exit(-1); leftMax + rightMax);
} }
13
// using divide-and-conquer if (nums[mid] - nums[0] !=
public static long power(int x, int n) (mid - 0) * diff) {
{ right = mid - 1;
// base condition }
if (n == 0) {
return 1L; // if the missing element lies
} on the right subarray, reduce
// our search space to the right
// calculate subproblem recursively subarray nums[mid+1…right]
long pow = power(x, n / 2); else {
left = mid + 1;
if ((n & 1) == 1) { // if `y` is odd }
return x * pow * pow; }
} return -1;
}
// otherwise, `y` is even
return pow * pow; public static void main(String[] args)
} {
int[] nums = { 5, 7, 9, 11, 15 };
public static void main(String[] args)
{ System.out.println("The missing term is "
int x = -2; + findMissingTerm(nums));
int n = 10; }
}
System.out.println("pow(" + x + ", " + n +
") = " + power(x, n)); Find floor and ceil of a number in a sorted array
} (Recursive solution)
} O(log(n))
class Main
Find the missing term in a sequence in logarithmic time {
O(log(n)) // Function to find the ceiling of `x` in a sorted array
class Main nums[low…high].
{ // i.e., the smallest integer greater than or equal to
// Function to find a missing term in a sequence `x`
public static int findMissingTerm(int[] nums) public static int findCeiling(int[] nums, int left, int
{ right, int x)
// search space is nums[left…right] {
int left = 0, right = nums.length - 1; // search space is nums[left…right]
// loop till the search space is exhausted // if `x` is less than equal to the lowest
while (left <= right) element in search
{ // space, the lowest element is the
// find the middle index ceiling
int mid = right - (right - left) / 2; if (x <= nums[left]) {
return nums[left];
// check the difference of }
middle element with its right neighbor
if (mid + 1 < nums.length && // if `x` is more than the highest element
nums[mid + 1] - nums[mid] != diff) { in the search space,
return nums[mid + // its ceiling doesn't exist
1] - diff; if (x > nums[right]) {
} return -1;
}
// check the difference of
middle element with its left neighbor // find the middle index
if (mid - 1 >= 0 && nums[mid] int mid = (left + right) / 2;
- nums[mid - 1] != diff) {
return nums[mid - 1] // if `x` is equal to the middle element, it
+ diff; is the ceiling
} if (nums[mid] == x) {
return nums[mid];
// if the missing element lies }
on the left subarray, reduce
// our search space to the right // if `x` is more than the middle element,
subarray nums[left…mid-1] the ceiling exists in the right
14
// subarray nums[mid+1…right] // subarray nums[left…mid-1]
else if (nums[mid] < x) { else {
return findCeiling(nums, mid + return findFloor(nums, left,
1, right, x); mid - 1, x);
} }
}
// if `x` is less than the middle element,
the ceiling exists in the left public static void main(String[] args)
// subarray nums[left…mid] (Note – {
middle element can also be ceiling) int[] nums = { 1, 4, 6, 8, 9 };
else {
return findCeiling(nums, left, for (int i = 0; i <= 10; i++)
mid, x); {
} System.out.printf("Number
} %2d —> ceiling is %2d, floor is %2d\n", i,
// Function to find the floor of `x` in a sorted array findCeiling(nums, 0, nums.length - 1, i),
nums[left…right].
// i.e., the largest integer less than or equal to `x` findFloor(nums, 0, nums.length - 1, i));
public static int findFloor(int[] nums, int left, int }
right, int x) }
{ }
// search space is nums[left…right]
Find the frequency of each element in a sorted array
// base case containing duplicates
if (nums.length == 0) { O(m.log(n))
return -1; m is the total number of distinct element
} import java.util.HashMap;
import java.util.Map;
// if `x` is less than the lowest element in
search class Main
// space, its floor doesn't exist {
if (x < nums[left]) { // Function to find the frequency of each element in
return -1; a sorted array
} public static void findFrequency(int[] nums, int left,
int right,
// if `x` is more than equal to the highest
element in Map<Integer, Integer> freq)
// the search space, it is the floor {
if (x >= nums[right]) { if (left > right) {
return nums[right]; return;
} }
15
{
int[] nums = { 2, 2, 2, 4, 4, 4, 5, 5, 6, 8, // return result
8, 9 }; return result;
}
// find the frequency of each array
element and store it in a map public static void main(String[] args)
Map<Integer, Integer> freq = new {
HashMap<>(); for (int i = 0; i <= 16; i++) {
findFrequency(nums, 0, nums.length - 1, System.out.printf("sqrt(%d) =
freq); %d\n", i, sqrt(i));
}
System.out.println(freq); }
} }
}
Division of two numbers using binary search algorithm
Find the square root of a number using a binary search O(log(n))
O(log(x)) class Main
{
class Main // Function to perform a division of two numbers
{ using the
// Function to find the square root of `x` using the // binary search algorithm
binary search algorithm. public static double divide(double x, double y)
// If `x` is not a perfect square, return the floor of {
the square root // handle divisibility by 0
public static int sqrt(int x) if (y == 0) {
{ return Double.MAX_VALUE;
// base case // return INFINITY
if (x < 2) { }
return x;
} // Set range for result [left, right].
// `right` is set to INFINITY to handle the
// to store floor of `sqrt(x)` case
int result = 0; // when `y < 1`, and `x < result <
Double.MAX_VALUE`
// the square root of `x` cannot be more double left = 0.0, right =
than `x/2` for `x > 1` Double.MAX_VALUE;
int start = 1;
int end = x/2; // set accuracy of the result
double precision = 0.001;
while (start <= end)
{ // store sign of the result
// find the middle element int sign = 1;
int mid = (start + end) / 2; if (x * y < 0) {
long sqr = mid*mid; sign = -1;
}
// return `mid` if `x` is a perfect
square // make both input numbers positive
if (sqr == x) { x = Math.abs(x);
return mid; y = Math.abs(y);
}
while (true)
// if `mid×mid` is less than `x` {
else if (sqr < x) // calculate mid
{ double mid = left + ((right -
// discard left search left) / 2);
space
start = mid + 1; // if `y×mid` is almost equal to
`x`, return `mid`
// update result if (Math.abs(y * mid - x) <=
since we need a floor precision) {
result = mid; return mid * sign;
} }
16
// if `y×mid` is more int[] nums = { 2, 2, 1, 1, 3, 3, 2, 2, 4, 4,
than `x`, update `right` to `mid` 3, 1, 1 };
right = mid;
} int index = findOddOccuring(nums, 0,
} nums.length - 1);
} System.out.println("The odd occurring
element is " + nums[index]);
public static void main(String[] args) { }
System.out.println(divide(22, 7)); }
}
} Find pairs with difference k in an array Constant Space
Solution
Find the odd occurring element in an array in O(n.log(n)).
logarithmic time import java.util.Arrays;
O(log(n))
class Main class Main
{ {
// Recursive function to find an odd occurring // Function to find a pair with the given difference
element in an array in the array.
// using binary search. This function assumes the // This method handles duplicates in the array
input is valid. public static void findPair(int[] A, int diff)
public static int findOddOccuring(int[] nums, int {
low, int high) // sort array in ascending order
{ Arrays.sort(A);
// base case
if (low == high) { // do for each array element
return low; for (int i = 0; i < A.length; i++)
} {
// to avoid printing duplicates
// find the middle index (skip adjacent duplicates)
int mid = (low + high) / 2; while (i < A.length - 1 && A[i]
== A[i+1]) {
// if `mid` is odd i++;
if (mid % 2 == 1) }
{
// if the element before `mid` is // perform a binary search on
the same as the middle element, the odd element `A[i]-diff`
// element lies on the right if (Arrays.binarySearch(A, A[i]
side; otherwise, it lies on the left side - diff) >= 0) {
if (nums[mid] == nums[mid -
1]) { System.out.println("(" + A[i] + ", " + (A[i] - diff) + ")");
return }
findOddOccuring(nums, mid + 1, high); }
} }
else {
return public static void main(String[] args)
findOddOccuring(nums, low, mid - 1); {
} int[] A = { 1, 5, 2, 2, 2, 5, 5, 4};
} int diff = 3;
17
while (right - left >= k) if (right - left == 1)
{ // common comparison
if (Math.abs(nums[left] - {
target) > Math.abs(nums[right] - target)) { if (nums[left] < nums[right])
left++; // comparison 1
} {
else { if (p.min >
right--; nums[left]) { // comparison 2
} p.min =
} nums[left];
}
return Arrays.stream(nums, left, right +
1).boxed() if (p.max <
nums[right]) { // comparison 3
.collect(Collectors.toList()); p.max =
} nums[right];
}
public static void main(String[] args) }
{ else {
int[] nums = {10, 12, 15, 17, 18, 20, 25 }; if (p.min >
int target = 16, k = 4; nums[right]) { // comparison 2
p.min =
nums[right];
System.out.println(findKClosestElements(nums, k, target)); }
}
} if (p.max <
nums[left]) { // comparison 3
Find the minimum and maximum element in an array p.max =
using Divide and Conquer nums[left];
O(n) }
// nums Pair class to wrap immutable primitive ints }
class Pair
{ return;
public int max, min; }
class Main
18
{ int data;
// Function to find the longest common prefix Node next;
between two strings
public static String LCP(String X, String Y) public Node(int data)
{ {
int i = 0, j = 0; this.data = data;
while (i < X.length() && j < Y.length()) this.next = null;
{ }
if (X.charAt(i) != Y.charAt(j)) { }
break;
} class Main
{
i++; j++; // Utility function to print contents of a linked list
} public static void printList(Node node)
{
return X.substring(0, i); while (node != null)
} {
System.out.print(node.data + "
// A recursive function to find the longest common —> ");
prefix (LCP) between a node = node.next;
// given set of strings }
public static String findLCP(List<String> words, int System.out.print("null");
low, int high) }
{
// base case: if `low` is more than `high`, // Takes two lists sorted in increasing order and
return an empty string merges their nodes
if (low > high) { // to make one big sorted list returned
return ""; public static Node sortedMerge(Node a, Node b)
} {
// base cases
// base case: if `low` is equal to `high`, if (a == null) {
return the current string return b;
if (low == high) { }
return words.get(low); else if (b == null) {
} return a;
}
// find the mid-index
int mid = (low + high) / 2; Node result;
// partition the problem into subproblems // pick either `a` or `b`, and recur
and recur for each subproblem if (a.data <= b.data)
String X = findLCP(words, low, mid); {
String Y = findLCP(words, mid + 1, result = a;
high); result.next =
sortedMerge(a.next, b);
// return the longest common prefix of }
strings `X` and `Y` else {
return LCP(X, Y); result = b;
} result.next = sortedMerge(a,
b.next);
public static void main(String[] args) }
{
List<String> words = return result;
Arrays.asList("techie delight", "tech", "techie", }
19
{ class Main
int i = 0, j = last; {
// Helper function to print a given linked list
// `(i, j)` forms a pair public static void printList(Node head)
while (i < j) {
{ Node ptr = head;
// merge list `j` with while (ptr != null)
`i` {
lists[i] = System.out.print(ptr.data + "
sortedMerge(lists[i], lists[j]); —> ");
ptr = ptr.next;
// consider the next }
pair
i++; System.out.println("null");
j--; }
// if all pairs are // Takes two lists sorted in increasing order and
merged, update last merge their nodes
if (i >= j) { // to make one big sorted list, which is returned
last = j; public static Node sortedMerge(Node a, Node b)
} {
} // base cases
} if (a == null) {
return b;
return lists[0]; }
} else if (b == null) {
return a;
public static void main(String[] s) }
{
int k = 3; // total number of linked lists Node result;
// an array to store the head nodes of // pick either `a` or `b`, and recur
the linked lists if (a.data <= b.data)
Node[] lists = new Node[k]; {
result = a;
lists[0] = new Node(1); result.next =
lists[0].next = new Node(5); sortedMerge(a.next, b);
lists[0].next.next = new Node(7); }
else {
lists[1] = new Node(2); result = b;
lists[1].next = new Node(3); result.next = sortedMerge(a,
lists[1].next.next = new Node(6); b.next);
lists[1].next.next.next = new Node(9); }
20
fast = fast.next;
if (fast != null) class Main
{ {
slow = slow.next; // Utility function to push a node at the beginning of
fast = fast.next; the doubly linked list
} public static Node push(Node head, int key)
} {
Node node = new Node(key);
// `slow` is before the midpoint in the list, node.next = head;
so split it in two
// at that point. // change `prev` of the existing head
Node[] arr = new Node[]{ source, node to point to the new node
slow.next }; if (head != null) {
slow.next = null; head.prev = node;
}
return arr;
} // return new head node
return node;
// Sort a given linked list using the merge sort }
algorithm
public static Node mergesort(Node head) // Helper function to print nodes of a doubly linked
{ list
// base case — length 0 or 1 public static void printDDL(Node head)
if (head == null || head.next == null) { {
return head; while (head != null)
} {
System.out.print(head.data + "
// split `head` into `a` and `b` sublists ⇔ ");
Node[] arr = frontBackSplit(head); head = head.next;
Node front = arr[0]; }
Node back = arr[1];
System.out.println("null");
// recursively sort the sublists }
front = mergesort(front);
back = mergesort(back); // Function to split nodes of the given doubly linked
list into
// answer = merge the two sorted lists // two halves using the fast/slow pointer strategy
return sortedMerge(front, back); public static Node split(Node head)
} {
Node slow = head;
public static void main(String[] args) Node fast = head.next;
{
// input keys // advance `fast` by two nodes, and
int[] keys = { 8, 6, 4, 9, 3, 1 }; advance `slow` by a single node
while (fast != null)
Node head = null; {
for (int key: keys) { fast = fast.next;
head = new Node(key, head); if (fast != null)
} {
slow = slow.next;
// sort the list fast = fast.next;
head = mergesort(head); }
}
// print the sorted list
printList(head); return slow;
} }
}
// Recursive function to merge nodes of two sorted
Sort a doubly-linked list using merge sort lists
O(n.log(n)) // into a single sorted list
// A Doubly Linked List Node public static Node merge(Node a, Node b)
class Node {
{ // base cases
int data; if (a == null) {
Node next, prev; return b;
}
Node(int data) {
this.data = data; if (b == null) {
} return a;
} }
21
num = Math.abs(num);
// pick either `a` or `b`, and recur
if (a.data <= b.data) // drop last bit from num (divide it by 2)
{ int i = num >> 1;
a.next = merge(a.next, b);
a.next.prev = a; // if num is odd
a.prev = null; if ((num & 1) == 1) {
return a; return ((findSquare(i) << 2) +
} (i << 2) + 1);
else { }
b.next = merge(a, b.next); // if num is even
b.next.prev = b; else {
b.prev = null; return (findSquare(i) << 2);
return b; }
} }
}
public static void main(String[] args) {
// Function to sort a doubly-linked list using merge System.out.print(findSquare(8));
sort algorithm }
public static Node mergesort(Node head) }
{
// base case: 0 or 1 node
if (head == null || head.next == null) {
return head;
}
head = mergesort(head);
printDDL(head);
}
}
class Main
{
public static int findSquare(int num)
{
// base case
if (num < 2) {
return num;
}
22