Algorithm for finding saddle-points in a 2-dimensional array - arrays

I'm looking for an algorithm to find the positions of all saddle points in an NxN matrix.
Searching through other answers on StackOverflow, as well as other sites in general, I've only found solutions regarding saddle points that operate in one direction. That is, I want to find a saddle point that can be a maximum in its row and minimum in its column, or a minimum in its row and maximum in its column.
For example, given:
array = {
{ 10, 15, 20, 15, 10 }
{ 5, 10, 15, 10, 5 }
{ 0, 5, 10, 5, 0 }
{ 5, 10, 15, 10, 5 }
{ 10, 15, 20, 15, 10 } },
the saddle points are the 10's in the corners and the 10 in the middle.
I can find them naively fairly easily, but I wanted something more efficient. I've been told it can be done in O(n^2).
I thought perhaps I could fix the x-coordinate and iterate through the y-coordinate to find all maximums and minimums, then reverse the process by fixing the y-coordinate and iterating through the x-coordinate, but I can't quite visualize it well enough to implement the idea.
Any help would be greatly appreciated.

Notice that in the naive implementation O(n3), you are recalculating the maximum value and minimum value for every element of a row/column you go through.
To eliminate this inefficiency, the idea is to loop through every row and column, and mark all positions with the maximum and minimum value in a separate N x N array. Each element of this separate array contains 2 pieces of boolean information: isMax and isMin (which can be encoded as bit if you want to). If all elements in a row/column are the same (i.e. maximum value = minimum value), then you might not want to mark any element.
For each row/column, this can be done in O(n) time. Use an n-element array to record the indices where the current maximum (minimum) value, and clear the array if there is a bigger (smaller) value than the current maximum (minimum). After you have finished looping through, use the information from the maximum (minimum) indices array to mark the corresponding isMax (isMin) field in the N x N array.
Since there are n rows and n columns, the complexity of this step is O(n2)
Then the rest is to loop through the N x N array which you have marked to search for any position with both isMax and isMin set.

O(n^2)
#include <stdio.h>
#define N 8
#define M 10
int arr[N][M] =
{ {1,2,0,3,9,4,5,3,6,7},
{2,4,3,5,9,0,2,3,4,1},
{5,3,4,7,6,1,9,0,4,2},
{6,9,7,8,6,7,7,4,5,6},
{8,3,1,9,2,0,6,2,8,2},
{2,7,3,0,3,6,3,1,5,3},
{8,2,5,9,7,7,8,3,7,3},
{1,7,4,8,5,8,5,0,0,6} };
int FindSaddlePoints(int arr[N][M])
{
int l_result = 0;
int l_row[M], l_column[N], i, j, index;
//find the min
for (i = 0; i < N; i++)
{
index = 0;
for (j = 1; j < M; j++)
{
if (arr[i][j] < arr[i][index])
{
index = j;
}
}
l_column[i] = index;
}
for (j = 0; j < M; j++)
{
index = 0;
//find the max
for (i = 1; i < N; i++)
{
if (arr[i][j] > arr[index][j])
{
index = i;
}
}
l_row[j] = index;
}
for (i = 0; i < N; i++)
{
for (j = 0; j < M; j++)
{
if (l_row[j] == i && l_column[i] == j && i != N && j != M)
{
//printf("found in row = %d column = %d", i, j);
l_result++;
}
}
}
return l_result;
}
void main()
{
int number = FindSaddlePoints(arr);
printf("%d", number);
}

Related

Sorting out Array of several integers, numbers in array seems to have shifted by 1

I'm trying to solve a question to find the lowest and highest numbers in an array in C Language. I tried swapping the numbers that are close to each other to align the numbers from small(left) to big(right).
For example, if the array is 20, 10, 35, 30, 7, first compare 20 and 10, if 20 is larger than 10, swap the numbers to 10, 20. then compare 20 and 35, 20 is smaller than 35, so go on. then compare 35 and 30, 35 is bigger than 30, swap numbers to 30, 35. then compare 35 and 7, 35 is bigger than 7, swap numbers to 7, 35.
Did these 'swappings' again 3 more times to align the numbers perfectly.
After I've done the swappings, I just printed the first array number and the last array number, but the numbers aren't correct, and it looks like the numbers have shifted by 1. For example, if I align the above array, it is 7[0], 10[1], 20[2], 30[3], 35[4]. (marked the indices by []) So, when I print the indice[0], and indice[4], I expected the numbers to show 7 and 35.
But in fact I have to print indice[1], and indice[5] to get the numbers 7 and 35 to be printed. The numbers seem to have shifted by 1..
I really want to know why the numbers have shifted by 1 in the array.
Thank you for reviewing the question.
I'll also post the original question that I'm trying to solve.
"Q. Input the number N first to decide how much numbers to enter, then input the N-numbers. Print the lowest and highest number in the N-numbers you have input."
And here's my code:
#include<stdio.h>
#pragma warning(disable:4996)
int main(void)
{
int input, i, j, temp, k;
int value[100] = { 0 };
scanf("%d", &input);
for (i = 0; i < input; i++)
{
scanf("%d", &value[i]);
}
for (k = 0; k < input; k++)
{
for (j = 0; j < input; j++)
{
if (value[j] > value[j + 1])
{
temp = value[j + 1];
value[j + 1] = value[j];
value[j] = temp;
}
}
}
printf("%d %d\n", value[0], value[input-1]);
return 0;
}
Because you're iterating over the whole array, value[j+1] walks off the end of the user's input. Since value was initialized 0 to, temp = value[j + 1] will be 0. So 0 will always be your min (unless the user enters negatives).
Instead, iterate only up to j < input - 1.
I'm trying to solve a question to find the lowest and highest numbers in an array in C Language.
You don't need to sort the array, you can do this in a single pass.
// Initialize min and max to be the first value.
int min = value[0];
int max = value[0];
// Then loop through the rest of the array checking if each value is
// smaller than min and/or larger than max.
for (i = 1; i < input; i++) {
if( value[i] < min ) {
min = value[i];
}
if( value[i] > max ) {
max = value[i];
}
}
printf("min: %d, max: %d\n", min, max);
Note: It's not necessary to declare all your variables up front. You can declare them as you need them. And you don't need different iterators for each loop, you can reuse i as I have above.

Finding the second Max in an unsorted dynamic array

I share with my solution of the algorithm to find the second maximum in a given unsorted array, is there a better way to do it? (I found complexity O(2n))
int PositionDuSecondMax(int *T, int n) {
// this function look for the index of the second maximum ( the number just under the maximum ) in a given array
// exemple : T[] = {10,100,14,49] ---> this function returns 3
// we have T a dynamic array and n the number of elements in T
// the given array in unsorted
int iMax = 0; // we suppose iMax == 0
int iSecMax;
// we go through the array and compare T[iMax] with the current element in the current index
// so we can find the index of the max in the array
for (int i = 0; i < n; i++) {
if (T[iMax] < T[i]) {
iMax = i;
}
}
// this if statement is to max sure that iMax is different from iSecMax
if (iMax == 0) {
iSecMax = 1;
} else {
iSecMax = iMax - 1;
}
// we loop through the array and compare each element with T[iSecMax] , we must specify that T[iSecMax] != T[iMax]
for (int i = 0; i < n; i++) {
if (T[iSecMax] < T[i] && T[iSecMax] == T[iMax]) {
iSecMax = i;
}
}
return iSecMax;
}
Your approach has multiple problems:
if the max is at offset 0 with a duplicate at offset 1 or if the max is at offset iMax - 1, the initial value of iSecMax is that of the maximum so you will not find the second max.
the test T[iSecMax] == T[iMax] to avoid select a duplicate of the max value is incorrect, it should be T[i] != T[iMax].
Here is a modified version:
int PositionDuSecondMax(const int *T, int n) {
// this function returns the index of the second maximum (the number just under the maximum) in a given array
// example: T[] = {10,100,14,49} --> this function returns 3
// arguments: T points to an unsorted array of int,
// n is the number of elements in T.
int iMax = 0;
int iSecMax = -1;
// we go through the array and compare T[iMax] with the
// element in the current index so we can find the index
// of the max in the array
for (int i = 1; i < n; i++) {
if (T[iMax] < T[i]) {
iMax = i;
}
}
// we loop through the array, ignoring occurrences of T[iMax] and
// compare each element with T[iSecMax]
for (int i = 0; i < n; i++) {
if (T[i] != T[iMax] && (iSecMax < 0 || T[iSecMax] < T[i])) {
iSecMax = i;
}
}
return iSecMax;
}
Notes:
the above function will return -1 if the array is empty or has all entries with the same value, ie: no second max value.
the complexity is O(n). O(2n) and O(n) are the same thing: O(n) means asymptotically proportional to n.
You could modify the code to perform a single scan with a more complicated test, and it would still be O(n).
If the array is unsorted, all elements must be tested so O(n) is the best one can achieve.
If the array was sorted, finding the second max would be O(1) on average (if the second to last element differs from the last), with a worst case of O(log n) (using binary search when the max has duplicates).
If you want to find second largest element in one traverse, you can follow below approach.
if (arrSize < 2)
{
printf(" Invalid Input ");
return;
}
first = second = INT_MIN;
for (i = 0; i < arrSize; i++)
{
/* If current element is greater than first
then update both first and second */
if (arr[i] > first)
{
second = first;
first = arr[i];
}
/* If arr[i] is in between first and
second then update second */
else if (arr[i] > second && arr[i] != first)
second = arr[i];
}
if (second == INT_MIN) printf("There is no second largest element\n");
else printf("The second largest element is %d\n", second);
The best approach is to visit each element of an array to find the second highest number in array with duplicates. The time complexity of this approach is O(n).
Algorithm :
i) Declare two variables max and second max and initialize them with integer minimum possible value.
ii) Traverse an array and compare each element of an array with the value assigned to max variable. If current element is greater than the value assigned at max variable. Then do two things –
a) In second max variable, assign the value present at max variable.
b) In max variable, assign the current index value.
iii) We have to do one more comparison that if current index value is less than max and greater than the value assigned at second max. Then, assign current index value at second max variable.
After complete iteration print the second max element of an array.
#include<stdio.h>
int secondLargest(int arr[], int len) {
//Initialize
int max = 0;
int second_max = 0;
for(int i = 0; i < len; i++) {
if(arr[i] > max) {
second_max = max;
max = arr[i];
}
if(max > arr[i] && arr[i] > second_max) {
second_max=arr[i];
}
}
return second_max;
}
int main(void) {
int arr[] = {70, 4, 8, 10, 14, 9, 7, 6, 5, 3, 2};
int len = 11;
printf("Second highest element is %d\n",secondLargest(arr,len));
return 0;
}

Rearrange an array so that arr[i] becomes arr[arr[i]] with O(1) extra space

The task is to rearrange an array so that arr[i] becomes arr[arr[i]] with O(1) extra space.
Example:
2 1 3 5 4 0
becomes:
3 1 5 0 4 2
I can think of an O(n²) solution. An O(n) solution was presented here:
Increase every array element arr[i] by (arr[arr[i]] % n)*n.
Divide every element by n.
But this is very limited as it will cause buffer overflow.
Can anyone come up with an improvement upon this?
If the values in the array are all positive (or all negative), one way to avoid overflow could be to run the permutation cycles and use the integer sign to mark visited indexes. (Alternatively, if the array length is smaller than 2^(number of bits for one array element - 1), rather than use the sign, we could shift all the values one bit to the left and use the first bit to mark visited indexes.) This algorithm results in both less iterations and less modifications of the original array values during run-time than the algorithm you are asking to improve.
JSFiddle: http://jsfiddle.net/alhambra1/ar6X6/
JavaScript code:
function rearrange(arr){
var visited = 0,tmp,indexes,zeroTo
function cycle(startIx){
tmp = {start: startIx, value: arr[startIx]}
indexes = {from: arr[startIx], to: startIx}
while (indexes.from != tmp.start){
if (arr[indexes.from] == 0)
zeroTo = indexes.to
if (indexes.to == visited){
visited++
arr[indexes.to] = arr[indexes.from]
} else {
arr[indexes.to] = -arr[indexes.from]
}
indexes.to = indexes.from
if (indexes.from != tmp.start)
indexes.from = arr[indexes.from]
}
if (indexes.to == visited){
visited++
arr[indexes.to] = tmp.value
} else {
arr[indexes.to] = -tmp.value
}
}
while (visited < arr.length - 1){
cycle(visited)
while (arr[visited] < 0 || visited == zeroTo){
arr[visited] = -arr[visited]
visited++
}
}
return arr
}
//Traverse the array till the end.
//For every index increment the element by array[array[index] % n]. To get //the ith element find the modulo with n, i.e array[index]%n.
//Again traverse to end
//Print the ith element after dividing the ith element by n, i.e. array[i]/n
class Rearrange
{
void rearrange(int arr[], int n)
{
for (int i = 0; i < n; i++)
arr[i] += (arr[arr[i]] % n) * n;
for (int i = 0; i < n; i++)
arr[i] /= n;
}
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
System.out.print(arr[i] + " ");
System.out.println("");
}
public static void main(String[] args)
{
Rearrange rearrange = new Rearrange();
int arr[] = {6, 4, 9, 2, 5, 7};
int n = arr.length;
System.out.println("Given Array is :");
rearrange.printArr(arr, n);
rearrange.rearrange(arr, n);
System.out.println("Modified Array is :");
rearrange.printArr(arr, n);
}
}

Kth smallest element in sorted matrix

This is an interview question.
Find the Kth smallest element in a matrix with sorted rows and columns.
Is it correct that the Kth smallest element is one of a[i, j] such as i + j = K ?
False.
Consider a simple matrix like this one:
1 3 5
2 4 6
7 8 9
9 is the largest (9th smallest) element. But 9 is at A[3, 3], and 3+3 != 9. (No matter what indexing convention you use, it cannot be true).
You can solve this problem in O(k log n) time by merging the rows incrementally, augmented with a heap to efficiently find the minimum element.
Basically, you put the elements of the first column into a heap and track the row they came from. At each step, you remove the minimum element from the heap and push the next element from the row it came from (if you reach the end of the row, then you don't push anything). Both removing the minimum and adding a new element cost O(log n). At the jth step, you remove the jth smallest element, so after k steps you are done for a total cost of O(k log n) operations (where n is the number of rows in the matrix).
For the matrix above, you initially start with 1,2,7 in the heap. You remove 1 and add 3 (since the first row is 1 3 5) to get 2,3,7. You remove 2 and add 4 to get 3,4,7. Remove 3 and add 5 to get 4,5,7. Remove 4 and add 6 to get 5,6,7. Note that we are removing the elements in the globally sorted order. You can see that continuing this process will yield the kth smallest element after k iterations.
(If the matrix has more rows than columns, then operate on the columns instead to reduce the running time.)
O(k log(k)) solution.
Build a minheap.
Add (0,0) to the heap. While, we haven't found the kth smallest element, remove the top element (x,y) from heap and add next two elements [(x+1,y) and (x,y+1)] if they haven't been visited before.
We are doing O(k) operations on a heap of size O(k) and hence the complexity.
This problem can be solved using binary search and optimised counting in a sorted Matrix. A binary search takes O(log(n)) time and for each search value it takes n iterations on average to find the numbers that are smaller than the searched number. The search space for binary search is limited to the minimum value in the Matrix at mat[0][0] and the maximum value mat[n-1][n-1].
For every number that is chosen from the binary search we need to count the numbers that are smaller than or equal to that particular number. And thus the smallest number can be found.
For better understanding you can refer to this video:
https://www.youtube.com/watch?v=G5wLN4UweAM&t=145s
Start traversing the matrix from the top-left corner (0,0) and use a binary heap for storing the "frontier" - a border between a visited part of the matrix and the rest of it.
Implementation in Java:
private static class Cell implements Comparable<Cell> {
private final int x;
private final int y;
private final int value;
public Cell(int x, int y, int value) {
this.x = x;
this.y = y;
this.value = value;
}
#Override
public int compareTo(Cell that) {
return this.value - that.value;
}
}
private static int findMin(int[][] matrix, int k) {
int min = matrix[0][0];
PriorityQueue<Cell> frontier = new PriorityQueue<>();
frontier.add(new Cell(0, 0, min));
while (k > 1) {
Cell poll = frontier.remove();
if (poll.y + 1 < matrix[poll.x].length) frontier.add(new Cell(poll.x, poll.y + 1, matrix[poll.x][poll.y + 1]));
if (poll.x + 1 < matrix.length) frontier.add(new Cell(poll.x + 1, poll.y, matrix[poll.x + 1][poll.y]));
if (poll.value > min) {
min = poll.value;
k--;
}
}
return min;
}
As people mentioned previously the easiest way is to build a min heap. Here's a Java implementation using PriorityQueue:
private int kthSmallestUsingHeap(int[][] matrix, int k) {
int n = matrix.length;
// This is not necessary since this is the default Int comparator behavior
Comparator<Integer> comparator = new Comparator<Integer>() {
#Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
};
// building a minHeap
PriorityQueue<Integer> pq = new PriorityQueue<>(n*n, comparator);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
pq.add(matrix[i][j]);
}
}
int ans = -1;
// remove the min element k times
for (int i = 0; i < k; i++) {
ans = pq.poll();
}
return ans;
}
Kth smallest element in the matrix :
The problem can be narrowed down as below.
if k is 20, then take k*k matrix (where answer will definitely lie.)
Now you can merge the rows in pair repeatedly to build a sorted array and then find the kth smallest number.
//int arr[][] = {{1, 5, 10, 14},
// {2, 7, 12, 16},
// {4, 10, 15, 20},
// {6, 13, 19, 22}
//};
// O(k) Solution
public static int myKthElement(int arr[][], int k) {
int lRow = 1;
int lCol = 0;
int rRow = 0;
int rCol = 1;
int count = 1;
int row = 0;
int col = 0;
if (k == 1) {
return arr[row][col];
}
int n = arr.length;
if (k > n * n) {
return -1;
}
while (count < k) {
count++;
if (arr[lRow][lCol] < arr[rRow][rCol]) {
row = lRow;
col = lCol;
if (lRow < n - 1) {
lRow++;
} else {
if (lCol < n - 1) {
lCol++;
}
if (rRow < n - 1) {
lRow = rRow + 1;
}
}
} else {
row = rRow;
col = rCol;
if (rCol < n - 1) {
rCol++;
} else {
if (rRow < n - 1) {
rRow++;
}
if (lCol < n - 1) {
rCol = lCol + 1;
}
}
}
}
return arr[row][col];
}

How to find 3 numbers in increasing order and increasing indices in an array in linear time

I came across this question on a website. As mentioned there, it was asked in amazon interview. I couldn't figure out a proper solution in given constraint.
Given an array of n integers, find 3 elements such that a[i] < a[j] < a[k] and i < j < k in O(n) time.
So here is how you can solve the problem. You need to iterate over the array three times. On the first iteration mark all the values that have an element greater than them on the right and on the second iteration mark all the elements smaller than them on their left. Now your answer would be with an element that has both:
int greater_on_right[SIZE];
int smaller_on_left[SIZE];
memset(greater_on_rigth, -1, sizeof(greater_on_right));
memset(smaller_on_left, -1, sizeof(greater_on_right));
int n; // number of elements;
int a[n]; // actual elements;
int greatest_value_so_far = a[n- 1];
int greatest_index = n- 1;
for (int i = n -2; i >= 0; --i) {
if (greatest_value_so_far > a[i]) {
greater_on_right[i] = greatest_index;
} else {
greatest_value_so_far = a[i];
greatest_index = i;
}
}
// Do the same on the left with smaller values
for (int i =0;i<n;++i) {
if (greater_on_right[i] != -1 && smaller_on_left[i] != -1) {
cout << "Indices:" << smaller_on_left[i] << ", " << i << ", " << greater_on_right[i] << endl;
}
}
This solution iterates 3 times over the whole array and is therefore linear. I have not provided the whole solution so that you can train yourself on the left to see if you get my idea. I am sorry not to give just some tips but I couldn't figure out how to give a tip without showing the actual solution.
Hope this solves your problem.
One-pass linear time, with O(1) extra space (4 variables). Very efficient (only a couple comparisons/branches per iteration, and not much data shuffling).
This is NOT my original idea or algorithm, I just tidied up and commented the code in an ideone fork. You can add new test-cases to the code there and run it online. The original is by Kenneth, posted in comments on a thread on www.geeksforgeeks.org. Great algorithm, but the original implementation had some really silly code outside of the actual loop. (e.g., instead of local variables, lets use two member-variables in a class, and implement the function as a member-function of class Solution... And the variable-names sucked. I went for quite verbose ones.)
Kenneth, if you want to post your code as an answer, go ahead. I'm not trying to steal credit for the algo. (I did put some work into writing up this explanation, and thinking through why it works, though.)
The main article above the discussion thread has the same solution as Ivaylo Strandjev's answer. (The main-article's code is what Pramod posted as an answer to this question, months after Ivalyo's answer. That's how I found the interesting answers in comments there.)
Since you only need to find a solution, not all of them, there aren't as many corner cases as you'd expect. It turns out you don't need to keep track of every possible start and middle value you've seen, or even backtrack at all, if you choose the right things to keep as state.
The main tricks are:
The last value in a sequence of monotonically decreasing values is the only one you need to consider. This applies to both first(low) and second(mid) candidate elements.
Any time you see a smaller candidate for a middle element, you can start fresh from there, just looking for either a final element or an even better mid-candidate.
If you didn't already find a sequence of 3 increasing elements before an element smaller than your current mid-candidate, min-so-far and the new smaller middle-candidate are as good (as forgiving, as flexible) as you can do out of the numbers you've already checked. (See the comments in the code for a maybe-better way of phrasing this.)
Several other answers make the mistake of starting fresh every time they see a new smallest or largest element, rather than middle. You track the current min that you've seen, but you don't react or make use of it until you see a new middle.
To find new candidate middle elements, you check if they're smaller than the current middle-candidate, and != min element seen so far.
I'm not sure if this idea can be extended to 4 or more values in sequence. Finding a new candidate 3rd value might require tracking the min between the current candidate second and third separately from the overall min. This could get tricky, and require a lot more conditionals. But if it can be done correctly with constant-size state and one pass without backtracking, it would still be linear time.
// Original had this great algorithm, but a clumsy and weird implementation (esp. the code outside the loop itself)
#include <iostream>
#include <vector>
using namespace std;
//Find a sorted subsequence of size 3 in one pass, linear time
//returns an empty list on not-found
vector<int> find3IncreasingNumbers(int * arr, int n)
{
int min_so_far = arr[0];
int c_low, c_mid; // candidates
bool have_candidates = false;
for(int i = 1; i < n; ++i) {
if(arr[i] <= min_so_far) // less-or-equal prevents values == min from ending up as mid candidates, without a separate else if()continue;
min_so_far = arr[i];
else if(!have_candidates || arr[i] <= c_mid) {
// If any sequence exists with a middle-numbers we've already seen (and that we haven't already finished)
// then one exists involving these candidates
c_low = min_so_far;
c_mid = arr[i];
have_candidates = true;
} else {
// have candidates and arr[i] > c_mid
return vector<int> ( { c_low, c_mid, arr[i] } );
}
}
return vector<int>(); // not-found
}
int main()
{
int array_num = 1;
// The code in this macro was in the original I forked. I just put it in a macro. Starting from scratch, I might make it a function.
#define TRYFIND(...) do { \
int arr[] = __VA_ARGS__ ; \
vector<int> resultTriple = find3IncreasingNumbers(arr, sizeof(arr)/sizeof(arr[0])); \
if(resultTriple.size()) \
cout<<"Result of arr" << array_num << ": " <<resultTriple[0]<<" "<<resultTriple[1]<<" "<<resultTriple[2]<<endl; \
else \
cout << "Did not find increasing triple in arr" << array_num << "." <<endl; \
array_num++; \
}while(0)
TRYFIND( {12, 11, 10, 5, 6, 2, 30} );
TRYFIND( {1, 2, 3, 4} );
TRYFIND( {4, 3, 1, 2} );
TRYFIND( {12, 1, 11, 10, 5, 4, 3} );
TRYFIND( {12, 1, 11, 10, 5, 4, 7} );
TRYFIND( {12, 11, 10, 5, 2, 4, 1, 3} );
TRYFIND( {12, 11, 10, 5, 2, 4, 1, 6} );
TRYFIND( {5,13,6,10,3,7,2} );
TRYFIND( {1, 5, 1, 5, 2, 2, 5} );
TRYFIND( {1, 5, 1, 5, 2, 1, 5} );
TRYFIND( {2, 3, 1, 4} );
TRYFIND( {3, 1, 2, 4} );
TRYFIND( {2, 4} );
return 0;
}
Making a CPP macro which can take an initializer-list as a parameter is ugly:
Is it possible to pass a brace-enclosed initializer as a macro parameter?
It was very much worth it to be able to add new test-cases easily, though, without editing arr4 to arr5 in 4 places.
I posted another approach to resolve it here.
#include<stdio.h>
// A function to fund a sorted subsequence of size 3
void find3Numbers(int arr[], int n)
{
int max = n-1; //Index of maximum element from right side
int min = 0; //Index of minimum element from left side
int i;
// Create an array that will store index of a smaller
// element on left side. If there is no smaller element
// on left side, then smaller[i] will be -1.
int *smaller = new int[n];
smaller[0] = -1; // first entry will always be -1
for (i = 1; i < n; i++)
{
if (arr[i] < arr[min])
{
min = i;
smaller[i] = -1;
}
else
smaller[i] = min;
}
// Create another array that will store index of a
// greater element on right side. If there is no greater
// element on right side, then greater[i] will be -1.
int *greater = new int[n];
greater[n-1] = -1; // last entry will always be -1
for (i = n-2; i >= 0; i--)
{
if (arr[i] > arr[max])
{
max = i;
greater[i] = -1;
}
else
greater[i] = max;
}
// Now find a number which has both a greater number on
// right side and smaller number on left side
for (i = 0; i < n; i++)
{
if (smaller[i] != -1 && greater[i] != -1)
{
printf("%d %d %d", arr[smaller[i]],
arr[i], arr[greater[i]]);
return;
}
}
// If we reach number, then there are no such 3 numbers
printf("No such triplet found");
return;
}
// Driver program to test above function
int main()
{
int arr[] = {12, 11, 10, 5, 6, 2, 30};
int n = sizeof(arr)/sizeof(arr[0]);
find3Numbers(arr, n);
return 0;
}
Just for fun:
In JAVA:
List<Integer> OrderedNumbers(int[] nums){
List<Integer> res = new LinkedList<>();
int n = nums.length;
//if less then 3 elements, return the empty list
if(n<3) return res;
//run 1 forloop to determine local min and local max for each index
int[] lMin = new int[n], lMax = new int[n];
lMin[0] = nums[0]; lMax[n-1] = nums[n-1];
for(int i=1; i<n-1; i++){
lMin[i] = Math.min(lMin[i-1], nums[i]);
lMax[n-i-1] = Math.max(lMax[n-i],nums[n-i-1]);
}
//if a condition is met where min(which always comes before nums[i] and max) < nums[i] < max, add to result set and return;
for(int i=1; i<n-1; i++){
if(lMin[i]<nums[i] && nums[i]<lMax[i]){
res.add(lMin[i]);
res.add(nums[i]);
res.add(lMax[i]);
return res;
}
}
return res;
}
This problem is very similar to computing the longest increasing subsequence, with the constraint that size of this subsequence must necessarily be equal to three. The LIS problem (with O(nlog(n)) solution) can easily be modified for this specific problem. This solution has O(n) single pass complexity with O(1) space.
This solution requires that only unique elements occur in the list. We use an online solution. As we encounter any new element, it has potential to extend the present most optimum subsequence or start a new subsequence. In this case, as the maximum length of increasing subsequence is three, any new element currently being processed can either extend a sequence of size 2 to 3 and 1 to 2. So we maintain active lists containing the most optimum elements.
In this particular problem, the maximum number of active lists we have to maintain are 2 - one of size 2 and another of size 1. As soon as we hit a list with size 3, we have our answer. We make sure each active list terminates with minimum number. For more detailed explanation of this idea, refer this.
At any point of time in the online solution, these two active lists will store the most efficient values of the list - the end of the list will be smallest element that can be placed there. Suppose the two lists are:
Size 2 list => [a,b]
Size 1 list => [c]
The initial list can be easily written (refer to the code below). Suppose the next number to be entered is d. Then cases (cascading in execution) are as follows:
Case 1: d > b.
We have our answer in this case, as a < b < d.
Case 2: b > d > a. In this the list of size 2 can be optimally represented by having end as d instead of b, as every element occurring after d greater than b will also be greater than d. So we replace b by d.
Case 3: d < c. As Case 1 and 2 fails, it automatically implies that d < a. In such a case, it may start a new list with size one. The list with size one is compared to get the most efficient active list. If this case is true, we replace c by d.
Case 4: Otherwise. This case implies that d < b and c < d. In such a case, the list of size 2 is inefficient. So we replace [a, b] by [c, d].
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int two_size_first;
int two_size_mid;
int one_size;
int end_index;
vector<int> arr;
Solution(int size) {
end_index = two_size_mid = two_size_first = one_size = -1;
int temp;
for(int i=0; i<size; i++) {
cin >> temp;
arr.push_back(temp);
}
}
void solve() {
if (arr.size() < 3)
return;
one_size = two_size_first = arr[0];
two_size_mid = INT_MAX;
for(int i=1; i<arr.size(); i++) {
if(arr[i] > two_size_mid) {
end_index = i;
return;
}
else if (two_size_first < arr[i] && arr[i] < two_size_mid) {
two_size_mid = arr[i];
}
else if (one_size > arr[i]) {
one_size = arr[i];
}
else {
two_size_first = one_size;
two_size_mid = arr[i];
}
}
}
void result() {
if (end_index != -1) {
cout << two_size_first << " " << two_size_mid << " " << arr[end_index] << endl;
}
else {
cout << "No such sequence found" << endl;
}
}
};
int main(int argc, char const *argv[])
{
int size;
cout << "Enter size" << endl;
cin >> size;
cout << "Enter " << size << " array elements" << endl;
Solution solution(size);
solution.solve();
solution.result();
return 0;
}
My Approach - O(N) time two passes O(1) space with two variables used
for each element of the array we visit we maintain the minimum possible to its left to check for whether this element may be the middle element and also keep record of minimum middle element to its left to check for whether this element may be a candidate third element or it may form a middle element with lower value than found so far.Initailise min so far and middle so far to INT_MAX,
Fr each element thus we have to check :
If a particular array element is greater than the minimum of middle element so far than this array element is the answer with thi as the third element and the min middle element as the mid element(We will have to search for the third element afterward by one pass)
Else If a particular array element is greater than the minimum so far than this element could be a candidate middle element and now we have to check if the candidate middle element is less than the current middle element if so update the current middle element
ELSE If a particular array element is less than the minimum so far then update the minimum so far with arr[i] .
So this way for each element of the array we visit we maintain the minimum possible to its left to check for whether this element may be the middle element and also keep record of minimum middle element to its left to check for whether this element may be a candidate third element or it may form a middle element with lower value than found so far.
#include
using namespace std;
int main()
{
int i,j,k,n;
cin >> n;
int arr[n];
for(i = 0;i < n;++i)
cin >> arr[i];
int m = INT_MAX,sm = INT_MAX,smi;// m => minimum so far found to left
for(i = 0;i < n;++i)// sm => smallest middle element found so far to left
{
if(arr[i]>sm){break;}// This is the answer
else if(arr[i] < m ){m = arr[i];}
else if(arr[i] > m){if(arr[i]<sm){sm = arr[i];smi = i;}}
else {;}
}
if((i < n)&&(arr[i]>sm))
{
for(j = 0;j < smi;++j){if(arr[j] < sm){cout << arr[j] << " ";break;}}
cout << sm << " " << arr[i]<< endl;
}
else
cout << "Such Pairs Do Not Exist" << endl;
return 0;
}
Here is my O(n) solution with O(1) space complexity:-
Just a function which returns a vector consisiting of three values(if exixts)
`vector<int> find3Numbers(vector<int> A, int N)
{
int first=INT_MAX,second=INT_MAX,third=INT_MAX,i,temp=-1;
vector<int> ans;
for(i=0;i<N;i++)
{
if(first!=INT_MAX&&second!=INT_MAX&&third!=INT_MAX)
{
ans.push_back(first);
ans.push_back(second);
ans.push_back(third);
return ans;
}
if(A[i]<=first)
{
if(second!=INT_MAX)
{
if(temp==-1)
{
temp=first;
}
first=A[i];
}
else
{
first=A[i];
}
}
else if(A[i]<=second)
{
second=A[i];
temp=-1;
}
else
{
if(temp!=-1)
{
first=temp;
}
third=A[i];
}
}
if(first!=INT_MAX&&second!=INT_MAX&&third!=INT_MAX)
{
ans.push_back(first);
ans.push_back(second);
ans.push_back(third);
return ans;
}
return ans;
}`
Here is O(n) time and O(1) space complexity solution for this problem
bool increasingTriplet(vector<int>& a) {
int i,n=a.size(),first=INT_MAX,second=INT_MAX;
if(n<3)
return false;
for(i=0;i<n;i++)
{
if(a[i]<=first)
first = a[i];
else if(a[i]<=second)
second = a[i];
else
return true;
}
return false;
}
This function returns true if there exists a pair of 3 elements which are in sorted increasing order in array.
You can also modify this function to print all 3 elements or their indexes. Just update their indexes as well along with variable first and second.
My solution below.
public boolean increasingTriplet(int[] nums) {
int min1 = Integer.MAX_VALUE;
int min2 = Integer.MAX_VALUE;
for (int i =0; i<nums.length; i++) {
if (nums[i]<min1) {
min1 = nums[i];
} else if (nums[i]<min2 && nums[i]>min1) {
min2=nums[i];
} else if (nums[i]>min2) {
return true;
}
}
return false;
}
Try to create two variables:
1. index_sequence_length_1 = index i such
a[i] is minimal number
2. index_sequence_length_2 = index j such
There is index i < j such that a[i] < a[j] and a[j] is minimal
Iterate over whole array and update this variables in each iteration.
If you iterate over element that is greater than a[index_sequence_length_2], than you found your sequence.
Sorry, i couldn't resist but to solve the puzzle...
Here is my solution.
//array indices
int i, j, k = -1;
//values at those indices
int iv, jv, kv = 0;
for(int l=0; l<a.length(); l++){
//if there is a value greater than the biggest value
//shift all values from k to i
if(a[l]>kv || j == -1 || i == -1){
i = j;
iv = jv;
j = k;
jv = kv
kv = a[l]
k = l
}
if(iv < jv && jv < kv && i < j && j < k){
break;
}
}
Iterate once and done:
public static int[] orderedHash(int[] A){
int low=0, mid=1, high=2;
for(int i=3; i<A.length; i++){
if(A[high]>A[mid] && A[mid]>A[low])
break;
if(A[low]>A[i])
low=mid=high=i;
else if(low == mid && mid == high)
mid = high = i;
else if(mid == high){
if(A[high]<A[i])
high = i;
else
mid = high = i;
}
else if(A[mid]<A[i])
high = i;
else if( A[high]<A[i]){
mid = high;
high =i;
}
else
mid=high=i;
}
return new int[]{A[low],A[mid],A[high]};
}//
Then test with main:
public static void main(String[] args) {
int[][] D = {{1, 5, 5, 3, 2, 10},
{1, 5, 5, 6, 2, 10},
{1, 10, 5, 3, 2, 6, 12},
{1, 10, 5, 6, 8, 12, 1},
{1, 10, 5, 12, 1, 2, 3, 40},
{10, 10, 10, 3, 4, 5, 7, 9}};
for (int[] E : D) {
System.out.format("%s GIVES %s%n", Arrays.toString(E), Arrays.toString(orderedHash(E)));
}
}
What if you build a max-heap O(n) and then do Extract-Max O(1) 3 times?
Here is a solution with only one iteration.
I am using stack to compute for each index k whether there exists two other indices i & j such that a[i] < a[j] < a[k].
bool f(vector<int> a) {
int n = a.size();
stack<int> s;
for (int i = 0; i < n; ++i)
{
while(!s.empty() and a[s.top()]>=a[i]){
s.pop();
}
if (s.size()>=2) // s.size()>=k-1
{
return 1;
}
s.push(i);
}
return 0;
}
And important thing is that we can extend this problem to M such indices in the general case instead of k indices.

Resources