Related
You are given two list of integers a and b of same length n, Find the count of strictly increasing sequences of integers
I[0] < I[1] < .. < I[n-1] such that min(a[i], b[i]) <= I[i] <= max(a[i], b[i]) for each i.
Eg.
a = [6,3,4,4]
b = [1,5,1,6]
Four possible solutions are possible
[1 3 4 5],
[1 3 4 6],
[2 3 4 5],
[2 3 4 6].
The length of both arrays will not exceed 100.
Each element is between 1 and 10000.```
Can someone provide a hint for this question? I am not able to figure out
You can use a dynamic programming approach here. The states of your DP will be the current index and last value ,like count_sequence(int index, int last_value) , loop through min(a[index], b[index]) to max(a[index], b[index]) ,if there is a value greater then last_value go to next index with current value like count_sequence(index+1, current_value), if you reach base case which is index>=n that means you find a sequence then return 1. Using this you can find every possible sequence.
With memorization, the complexity will be O(n*m),
n = array size, m = maximum element
JavaScript/node.js solution:
const a = [6, 3, 4, 4]
const b = [1, 5, 1, 6]
const n = a.length
let min = []
let max = []
for (let i = n - 1; i >= 0; i--) {
let itemMin = (min[i] = Math.min(a[i], b[i]))
let itemMax = (max[i] = Math.max(a[i], b[i]))
if (i > 0) {
const maxBefore = Math.max(a[i - 1], b[i - 1])
// max of before index, >= current min
if (maxBefore >= min[i]) {
itemMin = Math.min(maxBefore + 1, max[i])
}
}
if (i < n - 1) {
const minAfter = min[i + 1]
// min of after index, <= current or calculated min
if (itemMin >= minAfter) {
itemMin = Math.min(minAfter - 1, min[i])
}
// max correction
itemMax = Math.min(max[i], minAfter - 1)
}
// Test is solution possible, if not do something
if (itemMin < min[i] || itemMin > max[i]) {
throw new Error('Impossible to solve...')
}
if (itemMax < min[i] || itemMax > max[i]) {
throw new Error('Impossible to solve...')
}
// Set min and max values
min[i] = itemMin
max[i] = itemMax
}
// ***** Printing results
function printResult(min, max, str = '', item = 0) {
const n = min.length
for (let j = min[item]; j <= max[item]; j++) {
if (item < n - 1) {
printResult(min, max, `${item !== 0 ? str : ''}${j},`, item + 1)
} else {
console.log(`[${str}${j}]`)
}
}
}
printResult(min, max)
Given two arrays, one holding the min value and the other the max value for each index, you could define a simple recursive function to derive each possible increasing sequence, with the starting value at each position being the maximum of the current min value and the previously selected value plus 1.
Here's some Java code to illustrate:
static void incSeq(int[] min, int[] max, int[] res, int pos, int prev)
{
if(pos == min.length)
{
System.out.println("seq: " + Arrays.toString(res));
return;
}
for(int j = Math.max(prev+1, min[pos]); j <= max[pos]; j++)
{
res[pos] = j;
incSeq(min, max, res, pos+1, j);
}
}
However, if we consider input such as:
min = {1, 1, 1, 1}
max = {100, 100, 100, 5}
we can see that our function is going to do a lot of useless work iterating through values in the first three positions that will not be part of an increasing sequence.
We can fix this by recognizing that the maximum value we need to consider for position i is one less that the max value at position i+1. If we start at the last position and work backwards using this rule we can update the max array above to:
max = {2, 3, 4, 5}
Which will mean a lot less work for our recursive function.
Here's the complete code:
public static void main(String[] args)
{
int n = 4;
int[] a = {6,3,4,4};
int[] b = {1,5,1,6};
int[] min = new int[n];
int[] max = new int[n];
System.out.println("a: " + Arrays.toString(a));
System.out.println("b: " + Arrays.toString(b));
for(int i=0; i<n; i++)
{
min[i] = Math.min(a[i], b[i]);
max[i] = Math.max(a[i], b[i]);
}
System.out.println("min: " + Arrays.toString(min));
System.out.println("max: " + Arrays.toString(max));
// cap max values
for(int i=n-1; i>0; i--)
{
max[i-1] = Math.min(max[i-1], max[i]-1);
}
System.out.println("max: " + Arrays.toString(max) + "\n");
incSeq(min, max, new int[n], 0, 0);
}
static void incSeq(int[] min, int[] max, int[] res, int pos, int prev)
{
if(pos == min.length)
{
System.out.println("seq: " + Arrays.toString(res));
return;
}
for(int j = Math.max(prev+1, min[pos]); j <= max[pos]; j++)
{
res[pos] = j;
incSeq(min, max, res, pos+1, j);
}
}
Output:
a: [6, 3, 4, 4]
b: [1, 5, 1, 6]
min: [1, 3, 1, 4]
max: [6, 5, 4, 6]
max: [2, 3, 4, 6]
seq: [1, 3, 4, 5]
seq: [1, 3, 4, 6]
seq: [2, 3, 4, 5]
seq: [2, 3, 4, 6]
Let's have an increasing sequence of distinct non-negative integers {0, 2, 3, 4, 7, 10, 12}. What's the fastest way of telling how many pairs are at most a distance let's say D = 3 from each other?
For example here it would be: [0, 2], [0, 3], [2, 3], [2, 4], [3, 4], [4, 7], [7, 10], [10, 12], so 8.
My shot at this:
int arr[] = {0, 2, 3, 4, 7, 10, 12};
int arrLength = 7;
int k = 1;
int D = 3;
int sum = 0;
for (int i = 0; i < arrLength;) {
if (i + k < arrLength && arr[i + k] - arr[i] <= D) {
sum++;
k++;
}
else {
i++;
k = 1;
}
}
printf("Number of pairs: %d\n", sum);
It takes too much time for larger arrays. Is there any other way of exploiting the fact, that:
The sequence is always increasing.
There can't be two same numbers.
We don't need to print out the exact pairs, just the number of them.
The integers can't be negative.
We could somehow share already computed pairs to other iterations.
The else clause is very pessimistic. You don't need to reset k to 1. It is obvious that a[i+1] forms the pair with all values in the [i+2, i+k) range. Consider a sliding window, along the lines of (untested)
i = 0;
j = 1;
while (i < arrLen) {
while (j < arrlen && a[j] - a[i] <= D) {
j++;
}
i++;
sum += j - i;
if (i == j) {
j++;
}
}
with a linear time complexity.
You can do it by dynamic programming. If M(n) is number of specified pairs, we will have M(n) = M(n-1) + number of pairs of A[0..n-2] with A[n-1] which have less than D. To find the last part of the recursion, it can be computed by log(n) as they are sorted. Hence, the time complexity of this algorithm is T(n) = T(n-1) + log(n) = O(n log(n)).
I am dealing with a problem and that problem requires the answer to this as a subroutine. I know how to generate all subsequences from an array using bit manipulation but struggling to generate subsequences of even length.
For the sake of example, assume that there is an array A = [2, 5, 4, 2, 3, 1]
I want all the subsequences of even length i.e., of length 2, 4, and 6.
Edit 1: 1<=N<=1000 where N is the size of the array.
Since you already know how to generate all subsequences, then just remove the last element and generate all subsequences of the remaining array, but append the last back to each subsequence with an odd length.
Easy to prove that this generates all the even-length subsequences:
Every even-length subsequence of A that does not end in the last element of A, is an even-length subsequence of the earlier elements.
Every even-length subsequence of A that does end in the last element of A, has that element preceded by an odd-length subsequence of the earlier elements.
Subarrays
Using generator functions, you can take advantage of deferred execution to iterate all of the even-lengthed subarrays without retaining the entire collection of subarrays in memory:
function * subarrays (array) {
for (let length = 1; length <= array.length; length++) {
for (let index = 0; index + length <= array.length; index++) {
yield array.slice(index, index + length);
}
}
}
const filter = predicate => function * (iterator) {
for (const value of iterator) {
if (predicate(value)) yield value;
}
};
const even = filter(subarray => subarray.length % 2 === 0);
for (const subarray of even(subarrays ([2, 5, 4, 2, 3, 1]))) {
console.log(subarray.join());
}
However, if you do want the entire collection of even-lengthed subarrays, you can use Array.from() to consume the iterator and populate an array of subarrays:
function * subarrays (array) {
for (let length = 1; length <= array.length; length++) {
for (let index = 0; index + length <= array.length; index++) {
yield array.slice(index, index + length);
}
}
}
const filter = predicate => function * (iterator) {
for (const value of iterator) {
if (predicate(value)) yield value;
}
};
const even = filter(subarray => subarray.length % 2 === 0);
const result = Array.from(even(subarrays([2, 5, 4, 2, 3, 1])));
console.log(JSON.stringify(result));
Subsequences
To iterate all even-lengthed subsequences, one of the easiest methods is to keep a lookup table of which values to filter() from the array. We can achieve this with fairly minimal memory overhead by leveraging a Uint32Array:
function _increment (uint32Array) {
for (let index = 0; index < uint32Array.length; index++) {
// use unsigned integer overflow to
// perform carry in base 2**32 addition
if (++uint32Array[index]) return;
}
}
function * subsequences (array) {
const lut = new Uint32Array(Math.ceil(array.length / 32));
let subsequence;
while (true) {
yield subsequence = array.filter(
(_, index) => (lut[index >>> 5] >>> (index % 32)) & 1
);
if (subsequence.length === array.length) return;
_increment(lut);
}
}
const filter = predicate => function * (iterator) {
for (const value of iterator) {
if (predicate(value)) yield value;
}
};
const even = filter(({ length }) => (length > 0) && (length % 2 === 0));
for (const subsequence of even(subsequences([2, 5, 4, 2, 3, 1]))) {
console.log(subsequence.join());
}
#include <stdio.h>
#define N 4
const int A[] = { 2, 5, 4, 2, 3, 1, -1 };
int out[1000];
void gen(const int *p, int *pout) {
if(pout - out < N) {
while((*pout = *p++) > 0)
gen(p, pout + 1);
} else { // print output
for(const int *o = out; o < pout; o++)
printf("%d ", *o);
putchar('\n');
}
}
int main(int argc, char **argv) {
gen(A, out);
return 0;
}
Here's Python, which is as good as pseudocode:
def even_subsequences(L):
# yield the empty subsequence
yield []
# iterate over subsequence starting points
for i in range(len(L)):
# subsequence end point is the starting point plus an even number
for j in range(i+2, len(L)+1, 2):
# slice the list
yield L[i:j]
>>> list(even_subsequences([1,2,3,4,5,6]))
[[],
[1, 2],
[1, 2, 3, 4],
[1, 2, 3, 4, 5, 6],
[2, 3],
[2, 3, 4, 5],
[3, 4],
[3, 4, 5, 6],
[4, 5],
[5, 6]]
Let's say we have two arrays:
Array a1 and Array a2.
'a1' and 'a2' are similar in a way such that both have the same size and same elements but elements don't appear in the same order.
What will be the most effective way of comparing both arrays and finding out the minimum number of swaps required to bring the array 'a1' in the same order as 'a2'?
For example:
int a1[5] = { 1, 2, 3, 4, 5};
int a2[5] = { 2, 3, 1, 5, 4};
Hence the minimum number of swaps required is: 3
In steps:
swap 1: a1[0] <-> a1[1]
swap 2: a1[1] <-> a1[2]
swap 3: a1[3] <-> a1[4]
So, finally a1 will contain { 2, 3, 1, 5, 4}
int numofchanges = 0;
for(int i = 0; i < sizeOfArrays; i++)
{
int arr3[] = arr1;
for(int n = 0; n < sizeOfArrays; n++)
{
arr3[i] = arr1[n];
if(arr3[i] == arr2[i])
{
int tmp = arr1[i];
arr1[i] = arr1[n];
arr1[n] = tmp;
numofchanges++;
}
}
}
WARRNING this wont run is something like pseudo code
the variable numofchanges will hold the number of changes and arr1 now will be arr2
i hope this was helpful
I came across this question while in an interview and i am unable to find the best way to do it.
The question says, there are two 2d arrays, one is bigger than the other.
Lets say,
Array_1 = [[1,2],
[5,6]]
and
Array_2 = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12]]
Since, here the Array 2 contains Array 1, the algo should return true. Otherwise, false.
The size of the array can be anything.
Try this.
function Test() {
var x = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]];
var y = [[6, 7], [10, 12]];
for (i = 0; i < x.length; i++) {
for (j = 0; j < x[i].length; j++) {
if (x[i][j] == y[0][0])
if (findMatch(x, y, i, j)) {
console.log("Match Found");
return true;
}
}
}
console.log("Not found");
return false;
}
function findMatch(x, y, i, j) {
var b = true;
for (k = i; k < y.length; k++) {
for (n = j; n < y[k].length; n++) {
if (y[k - i][n - j] != x[k][n]) {
b = false;
break;
}
}
}
return b;
}
Note that this doesn't match if the smaller array is rotated inside the big array.(Written in javaScript)
I would fill in the smaller array to the bigger dimensions with null values (or with NaN), convert to 1D and truncate/strip the unnecessary nulls :
array_1 = [1, 2, null, null, 5, 6]
array_2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
then compare the 1D arrays, while skipping the null values - this would be O(n*m) in the worst case (such as [1,1,1,2] vs [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]), and it would be O(n) in the best case (if every number in the bigger array was different)
Edit: more logic is needed to ensure comparison only within the complete rows of the bigger array, not across rows...
I guess you could convert the arrays to dictionaries of positions and figure out a bit more complicated and faster algorithm if you need to do multiple comparisons...
You could also rotate the smaller array if needed, e.g.:
array_1_270 = [6, 2, null, null, 1, 5]
You can try aho-corasick algorithm for 2 dimension. Aho-corasick algorithm is the fastest multiple pattern matching. Here is a similar question:is there any paper or an explanation on how to implement a two dimensional KMP?
Maybe a little simpler in Python 2.6
def check():
small=[[1,2],[5,6]] #matches upper left corner
smallrows = len(small) #rows = 2
smallcols = len(small[0]) #cols = 2
big=[[1,2,3,4],[5,6,7,8],[9,10,11,12]]
bigrows = len(big) #rows = 3
bigcols = len(big[0]) #cols = 4
for i in range(bigrows-smallrows+1): #i is number row steps
for j in range(bigcols-smallcols+1): #j is number col steps
flag = 0
for k in range(smallrows):
for l in range(smallcols):
if big[i+k][j+l] != small[k][l]:
flag = 1
continue
if flag == 0:
return(True)
return(False)
print check()