I'm reading this excellent tutorial by Dumitru on DP based problems here. And I'm trying to come up with a DP based approach for the FlowerGarden problem mentioned in the list of 1D DP problems.
I can only think of a non-DP solution that would involve initially sorting the flowers in an order and then reordering them based on different condition checks mentioned in the problem. That doesn't classify as DP, does it?
The editorial also doesn't mention anything about DP.
Could anyone, by any chance, point me to a proper DP-based solution to this problem?
Thanks!
Edit:
I didn't realize the link would require registration. This is the problem:
Problem Statement
You are planting a flower garden with bulbs to give you joyous flowers throughout the year. However, you wish to plant the flowers
such that they do not block other flowers while they are visible.
You will be given a int[] height, a int[] bloom, and a int[] wilt.
Each type of flower is represented by the element at the same index of
height, bloom, and wilt. height represents how high each type of
flower grows, bloom represents the morning that each type of flower
springs from the ground, and wilt represents the evening that each
type of flower shrivels up and dies. Each element in bloom and wilt
will be a number between 1 and 365 inclusive, and wilt[i] will always
be greater than bloom[i]. You must plant all of the flowers of the
same type in a single row for appearance, and you also want to have
the tallest flowers as far forward as possible. However, if a flower
type is taller than another type, and both types can be out of the
ground at the same time, the shorter flower must be planted in front
of the taller flower to prevent blocking. A flower blooms in the
morning, and wilts in the evening, so even if one flower is blooming
on the same day another flower is wilting, one can block the other.
You should return a int[] which contains the elements of height in the
order you should plant your flowers to acheive the above goals. The
front of the garden is represented by the first element in your return
value, and is where you view the garden from. The elements of height
will all be unique, so there will always be a well-defined ordering.
Edit two:
Example 1:
height={5,4,3,2,1}
bloom={1,1,1,1,1}
wilt={365,365,365,365,365}
Returns: { 1, 2, 3, 4, 5 }
These flowers all bloom on January 1st and wilt on December 31st. Since they all may block each other, you must order them from shortest to tallest.
Example 2:
h={5,4,3,2,1}
b={1,5,10,15,20}
w={4,9,14,19,24}
Returns: { 5, 4, 3, 2, 1 }
The same set of flowers now bloom all at separate times. Since they will never block each other, you can order them from tallest to shortest to get the tallest ones as far forward as possible.
Example 3:
height={5,4,3,2,1}
bloom={1,5,10,15,20}
wilt={5,10,14,20,25}
Returns: { 3, 4, 5, 1, 2 }
The difference here is that the third type of flower wilts one day earlier than the blooming of the fourth flower. Therefore, we can put the flowers of height 3 first, then the flowers of height 4, then height 5, and finally the flowers of height 1 and 2. Note that we could have also ordered them with height 1 first, but this does not result in the maximum possible height being first in the garden.
It's not a dynamic programming problem. It's a greedy algorithm problem.
This confused me too, since topcoder's own dynamic programming tutorial links to it as a practice problem in the “Elementary” section.
Sort the flowers by height, shortest to tallest. Start with an empty list of rows. For each flower (shortest to tallest), find the forward-most place where you can insert that flower such that it blocks no flowers behind it.
In Python:
def getOrdering(height, bloom, wilt):
flowers = zip(height, bloom, wilt)
flowers.sort()
def flowersOverlap(f1, f2):
# Overlap if each blooms before the other wilts.
return f2[1] <= f1[2] and f1[1] <= f2[2]
rows = [ ]
for flower in flowers:
rowIndex = len(rows)
# Start at the back and march forward as long as
# `flower` wouldn't block any flowers behind it.
while rowIndex > 0 and not flowersOverlap(flower, rows[rowIndex - 1]):
rowIndex -= 1
rows[rowIndex:rowIndex] = [flower]
return [flower[0] for flower in rows]
public int[] getOrdering(int[] height, int[] bloom, int[] wilt) {
int[] optimal = new int[height.length];
int[] optimalBloom = new int[bloom.length];
int[] optimalWilt = new int[wilt.length];
// init state
optimal[0] = height[0];
optimalBloom[0] = bloom[0];
optimalWilt[0] = wilt[0];
// run dynamic programming
for(int i = 1; i < height.length; i ++) {
int currHeight = height[i];
int currBloom = bloom[i];
int currWilt = wilt[i];
int offset = 0; // by default, type i is to be put to 1st row
for(int j = 0; j < i; j ++) {
if(currWilt >= optimalBloom[j] && currWilt <= optimalWilt[j] ||
currBloom >= optimalBloom[j] && currBloom <= optimalWilt[j] ||
currWilt >= optimalWilt[j] && currBloom <= optimalBloom[j]) { // life period overlap
if(currHeight < optimal[j]) { // life overlap, and type i is shorter than type j
offset = j;
break;
} else {
offset = j + 1; // type i overlap with type j, and i is taller than j. Put i after j
}
} else { // not overlap with current
if(currHeight < optimal[j]) {
offset = j + 1; // type i not overlap with j, i is shorter than j, put i after j
}
// else keep offset as is considering offset is smaller than j
}
}
// shift the types after offset
for(int k = i - 1; k >= offset; k -- ) {
optimal[k+1] = optimal[k];
optimalBloom[k+1] = optimalBloom[k];
optimalWilt[k+1] = optimalWilt[k];
}
// update optimal
optimal[offset] = currHeight;
optimalBloom[offset] = currBloom;
optimalWilt[offset] = currWilt;
}
return optimal;
}
This is my tested working code.
I'have been struggling with this exact question for a whole day, and also, i couldn't find any DP solution to it.
Here is my greedy approach in java, similar to others already posted, the key point is to proceed under a height ordering. The reason is to avoid dealing with intermediate heights (referring to the already computed), given that a intermediate height can change the relative order of the previously computed ones.
int[] height = new int[]{5, 3, 4};
int[] start = new int[]{1, 3, 1};
int[] end = new int[]{2, 4, 4};
System.out.println(Arrays.toString(new FlowerGarden().getOrdering(height, start, end)));
This is the only optimal substructure I could find. But given that there is no overlapping among subproblems, this algorithm should not be considered DP but greedy.
private static boolean intersects(final int[] starts, final int[] ends, int i1, int i2) {
return !(ends[i1] < starts[i2] || ends[i2] < starts[i1]);
}
public int[] getOrdering(final int[] height, final int[] starts, final int[] ends) {
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {
public int compare(Integer i, Integer j) {
return Integer.compare(height[i], height[j]);
}
}
);
for (int i = 0; i < height.length; i++) {
minHeap.add(i);
}
LinkedList<Integer> list = new LinkedList<Integer>();
while (minHeap.size() > 0) {
Integer index = minHeap.poll();
int p = 1;
int pos = 0;
for (Integer i : list) {
if (intersects(starts, ends, i, index)) {
pos = p;
}
p++;
}
list.add(pos, index);
}
int[] ret = new int[height.length];
int j = 0;
for (Integer i : list) {
ret[j++] = height[i];
}
return ret;
}
BTW, the DP solutions I have seen posted here fail for this example.
Cheers
I tried to solve this problem too. The main idea of my approach is to build a tree where each child is overlaped at least once by its parent.
For example, if we have three flower types of heigths 4,2 and 1 growing and dying on the same days, then, the resulting tree should be:
On the other hand, if 4 and 2 and 4 and 1 live at the same time but 2 and 1 do not coexist then, the resulting tree should be:
That will generate a tree which is consistent with the problem contraints. Nonetheless the problem statement also includes a cost function making some solutions better than others.
...you also want to have the flowers in rows which are more towards the front be as tall as possible.
The way to project this preference into our tree is to order all "brothers" (all nodes sharing the same parent) from higher to lower. So 2 comes first than 1.
I built this tree using the following code:
#define INT_MOD(a,b) ((a<0)?(b+(a%b)):(a%b))
#define DIST(a,b) ((a-b>=0)?(a-b):(b-a))
//Prev: ForAll(i), bloom[i] < wilt[i]
inline bool isOverlap(vector<int> & bloom,
vector<int> & wilt,
vector<int> & height,
unsigned int idxPrev, unsigned int idxFollowing)
{
int f1A = bloom[idxPrev];
int f1B = wilt[idxPrev];
int f2A = bloom[idxFollowing];
int f2B = wilt[idxFollowing];
bool notIntersecting =
f2A > f1B /* --[--]-(--)-- */ ||
f1A > f2B /* --(--)-[--]-- */ ;
return height[idxPrev] > height[idxFollowing] && !notIntersecting;
}
class CPreference {
public:
static vector<int> * pHeight;
static bool preference(int a, int b)
{
return (*pHeight)[a] > (*pHeight)[b];
}
};
vector<int> * CPreference::pHeight = NULL;
vector<int> getOrdering(vector<int> height,
vector<int> bloom,
vector<int> wilt)
{
int l = height.size();
vector<int> state = vector<int>(l, -1); /* Tree where each leave points to its
parent. Being that parent the first
flower type that is forced to be
after (backwards) its children */
//This loop is the dynamic programming core.
for(int i = 0; i < l; i++)
for(int j = INT_MOD((i-1),l); j != i; j = INT_MOD((j-1),l))
{
if(isOverlap(bloom, wilt, height, i, j) &&
(state[j] < 0 || DIST(height[j],height[i]) < DIST(height[j], height[state[j]])))
{
state[j] = i;
}
}
vector<vector<int> > groups; //Groups of indexes overlapped by the element at the same index
for(int i = 0; i < l+1; i++)
groups.push_back(vector<int>()); // (l+1) for no overlapped indexes group.
for(int i = 0; i < l; i++)
{
int k = state[i];
if(k < 0) k = l;
groups[k].push_back(i);
}
CPreference::pHeight = &height;
for(vector<vector<int> >::iterator it = groups.begin(); it != groups.end(); it++)
sort(it->begin(),it->end(), CPreference::preference);
At this point, Each row (i) of groups contains, ordered from higher to lower, all flower types indexes that should be placed before the flower type of index i.
One last step is needed, to flatten groups into an output vector. That is, to build a vector where each element is followed by either:
Its parent on the tree.
It next brother when sorted by height.
That can be done by a depth visit of each node of group. I think that is the weak point of my solution. I had not so much time so I just made a naive recursive implementation:
//PRE: each vector, v, in 'groups' is sorted using CPreference
void flattenTree(vector<vector<int> > & groups, vector<int> & out, int currentIdx /*parent*/, int l)
{
int pIdx = currentIdx;
if(pIdx < 0) pIdx = l;
vector<int> & elements = groups[pIdx];
vector<int> ret;
for(vector<int>::iterator it = elements.begin(); it != elements.end(); it++)
{
flattenTree(groups, out ,*it, l);
}
if(currentIdx>=0)
out.push_back(currentIdx);
}
Which is used to completed getOrdering function:
vector<int> getOrdering(vector<int> height,
vector<int> bloom,
vector<int> wilt)
{
int l = height.size();
vector<int> state = vector<int>(l, -1); /* Tree where each leave points to its
parent. Being that parent the first
flower type that is forced to be
after (backwards) its children */
for(int i = 0; i < l; i++)
for(int j = INT_MOD((i-1),l); j != i; j = INT_MOD((j-1),l))
{
if(isOverlap(bloom, wilt, height, i, j) &&
(state[j] < 0 || DIST(height[j],height[i]) < DIST(height[j], height[state[j]])))
{
state[j] = i;
}
}
vector<vector<int> > groups; //Groups of indexes overlapped by the element at the same index
for(int i = 0; i < l+1; i++)
groups.push_back(vector<int>()); // (l+1) for no overlapped indexes group.
for(int i = 0; i < l; i++)
{
int k = state[i];
if(k < 0) k = l;
groups[k].push_back(i);
}
CPreference::pHeight = &height;
for(vector<vector<int> >::iterator it = groups.begin();
it != groups.end(); it++)
sort(it->begin(),it->end(), CPreference::preference);
vector<int> ret;
flattenTree(groups, ret, -1, l);
for(unsigned int i = 0; i < ret.size(); i++)
ret[i] = height[ret[i]];
return ret;
}
Please, let my know if you found a better solution or if know any way to improve mine.
package topcoders;
import java.util.ArrayList;
import java.util.List;
public class FlowerGarden {
public int[] getOrdering(int[] height, int[] bloom, int[] wilt) {
int[] order = new int[height.length];
List<Integer> heightList = new ArrayList<Integer>();
for (int i = 0; i < height.length; i++) {
heightList.add(height[i]);
}
heightList = quickSort(heightList);
for (int i = 0; i < height.length; i++) {
height[i] = heightList.get(i);
}
order = height;
for (int i = 0; i < order.length; i++) {
int j = 0;
while (j < order.length - 1
&& isBlocking(j + 1, j, order, bloom, wilt)) {
int placeHolder = order[j];
order[j] = order[j + 1];
order[j + 1] = placeHolder;
j++;
}
}
return order;
}
public boolean isBlocking(int isBlocked, int isBlocking, int[] order,
int[] bloom, int[] wilt) {
if (order[isBlocking] > order[isBlocked]
&& bloom[isBlocked] <= wilt[isBlocking]
&& wilt[isBlocked] >= bloom[isBlocking]) {
return true;
} else {
return false;
}
}
public List<Integer> quickSort(List<Integer> array) {
if (array.size() <= 1) {
return array;
}
int pivotIndex = array.size() / 2;
int pivot = array.get(pivotIndex);
List<Integer> less = new ArrayList<Integer>();
List<Integer> greater = new ArrayList<Integer>();
int l = 0;
int g = 0;
for (int i = 0; i < array.size(); i++) {
if (i == pivotIndex) {
continue;
} else if (array.get(i) >= pivot) {
less.add(array.get(i));
} else {
greater.add(array.get(i));
}
}
List<Integer> lessResult = quickSort(less);
List<Integer> greaterResult = quickSort(greater);
List<Integer> result = new ArrayList<Integer>();
result.addAll(lessResult);
result.add(pivot);
result.addAll(greaterResult);
return result;
}
public static void main(String[] args) {
int[] height = { 5, 4, 3, 2, 1 };
int[] bloom = { 1, 5, 10, 15, 20 };
int[] wilt = { 5, 10, 14, 20, 25 };
FlowerGarden g = new FlowerGarden();
List<Integer> arrayList = new ArrayList<Integer>();
int[] array = g.getOrdering(height, bloom, wilt);
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
A toplogical sort approach:
#include<stdio.h>
#include<stdlib.h>
#include <vector>
#include <queue>
using namespace std;
#define MAX_FLOWERS 50
struct flower
{
int id;
int height;
int bloom;
int wilt;
bool visited;
int ind;
};
struct flower_comp
{
bool operator()(const struct flower* lhs, const struct flower* rhs) const
{
return rhs->height > lhs->height;
}
};
inline bool overlap(const struct flower& a, const struct flower& b)
{
return !((a.bloom < b.bloom && a.wilt < b.bloom) || (a.bloom > b.bloom && a.bloom > b.wilt));
}
void getOrdering(int height[], int bloom[], int wilt[], int size)
{
struct flower flowers[MAX_FLOWERS];
for(int i = 0; i < size; i++)
{
flowers[i].id = i;
flowers[i].height = height[i];
flowers[i].bloom = bloom[i];
flowers[i].wilt = wilt[i];
flowers[i].visited = false;
flowers[i].ind = 0;
}
bool partial_order[MAX_FLOWERS][MAX_FLOWERS] = {false};
for(int i = 0; i < size; i++)
{
for(int j = i + 1; j < size; j++)
{
if(overlap(flowers[i], flowers[j]))
{
if(flowers[i].height < flowers[j].height)
{
partial_order[i][j] = true;
flowers[j].ind++;
}
else
{
partial_order[j][i] = true;
flowers[i].ind++;
}
}
}
}
priority_queue<struct flower*, vector<struct flower*>, flower_comp> pq;
for(int i = 0; i < size; i++)
{
if(flowers[i].ind == 0)
{
pq.push(&flowers[i]);
}
}
printf("{");
bool first = true;
while(!pq.empty())
{
struct flower* tmp = pq.top();
pq.pop();
tmp->visited = true;
if(!first)
{
printf(",");
}
first = false;
printf("%d", tmp->height);
for(int j = 0; j < size; j++)
{
if(!flowers[j].visited && partial_order[tmp->id][j])
{
flowers[j].ind--;
if(flowers[j].ind == 0)
{
pq.push(&flowers[j]);
}
}
}
}
printf("}\n");
}
int main(int argc, char** argv)
{
int height[] = {5,4,3,2,1};
int bloom[] = {1,1,1,1,1};
int wilt[] = {365,365,365,365,365};
getOrdering(height, bloom, wilt, sizeof(height)/sizeof(height[0]));
int height0[] = {5,4,3,2,1};
int bloom0[] = {1,5,10,15,20};
int wilt0[] = {4,9,14,19,24};
getOrdering(height0, bloom0, wilt0, sizeof(height0)/sizeof(height0[0]));
int height1[] = {5,4,3,2,1};
int bloom1[] = {1,5,10,15,20};
int wilt1[] = {5,10,15,20,25};
getOrdering(height1, bloom1, wilt1, sizeof(height1)/sizeof(height1[0]));
int height2[] = {5,4,3,2,1};
int bloom2[] = {1,5,10,15,20};
int wilt2[] = {5,10,14,20,25};
getOrdering(height2, bloom2, wilt2, sizeof(height2)/sizeof(height2[0]));
int height3[] = {1,2,3,4,5,6};
int bloom3[] = {1,3,1,3,1,3};
int wilt3[] = {2,4,2,4,2,4};
getOrdering(height3, bloom3, wilt3, sizeof(height3)/sizeof(height3[0]));
int height4[] = {3,2,5,4};
int bloom4[] = {1,2,11,10};
int wilt4[] = {4,3,12,13};
getOrdering(height4, bloom4, wilt4, sizeof(height4)/sizeof(height4[0]));
}
Same thing as Rob's but in Javascript (ES6):
function getOrdering(height, bloom, wilt) {
var n = height.length;
var idx = [];
for (var i = 0; i < n; ++i) idx[i] = i;
idx.sort( (a, b) => height[a] - height[b] );
var intersect = (a, b) => !(bloom[a] > wilt[b] || bloom[b] > wilt[a]);
for (var i = 1; i < n; ++i) {
// assume they are ordered correctly till index (i-1),
// start moving flower i to the left until it can't move because of intersection
var j = i, flw = idx[i];
while (j > 0 && !intersect(idx[j-1], flw)) {
idx[j] = idx[j-1];
idx[--j] = flw;
}
}
return idx.map( x => height[x] );
}
Similar to Rob, again in Python and slightly convoluted overlapping bloom/wilt check.
H = 0
B = 1
W = 2
def getOrdering(heights, blooms, wilts):
def _f1_after_f2(f1, f2):
fs1 = set(range(f1[B], f1[W]+1))
fs2 = set(range(f2[B], f2[W]+1))
return f1[H] > f2[H] if fs2.intersection(fs1) != set([]) else False
fs = zip(heights, blooms, wilts)
fs.sort()
ffs = []
for f1 in fs:
insert_at = len(ffs)
for f2 in reversed(ffs):
if _f1_after_f2(f1, f2): break
insert_at -= 1
ffs.insert(insert_at, f1)
return [f[H] for f in ffs]
A graph algorithm to solve the problem:
Create a directed graph(V,E):
V -> flower types
E -> relations between 2 flower types
For all pairs (v_i, v_j)
If v_i is smaller than v_j and v_j 'blocks' v_i
draw an edge starting from v_i to v_j
For all nodes v_i
Find the v_i with no incoming edges and the biggest height
-> write it at the end of the result list
-> remove v_i and all of its outgoing edges from graph
For more description checkout this forum:
Topcoder Forum - FlowerGarden
Mine is like insertion sort. For each new flower, it goes from back to front and checks to see if the one in front of it blocks it; if it does, it means it must be placed behind it. Likewise, it also searches from front to back and checks to see if the one behind it blocks it; if it does, it means it must be placed in front of it. If there are no blocks, it simply checks for the best spot height-wise.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#define uint32 uint32_t
static void
Swap(int *AIdx, int *BIdx)
{
int Tmp = *AIdx;
*AIdx = *BIdx;
*BIdx = Tmp;
}
static void
SwapTo(int Start, int End, int *Array)
{
while(Start != End)
{
Swap(&Array[Start], &Array[Start - 1]);
--Start;
}
}
static void
PrintTo(int End, int *Array)
{
for(int Idx = 0;
Idx < End;
++Idx)
{
printf("%d, ", Array[Idx]);
}
printf("\n");
}
/* Does A block B? */
static bool
Blocks(int AIdx, int BIdx, int *Heights, int *Blooms, int *Wilts)
{
bool Result = (Heights[AIdx] > Heights[BIdx] &&
Wilts[AIdx] >= Blooms[BIdx] &&
Blooms[AIdx] <= Wilts[BIdx]);
return Result;
}
static void
Order(int *Heights, int *Blooms, int *Wilts,
int FlowerCount)
{
for(int FlowerIdx = 1;
FlowerIdx < FlowerCount;
++FlowerIdx)
{
PrintTo(FlowerIdx, Heights);
/* front to back */
int MinIdx = -1;
for(int Idx = 0;
Idx < FlowerIdx;
++Idx)
{
if(Blocks(Idx, FlowerIdx, Heights, Blooms, Wilts))
{
MinIdx = Idx;
break;
}
}
/* back to front */
int MaxIdx = -1;
for(int Idx = (FlowerIdx - 1);
Idx >= 0;
--Idx)
{
if(Blocks(FlowerIdx, Idx, Heights, Blooms, Wilts))
{
MaxIdx = (Idx + 1);
break;
}
}
/* best height index */
int BestHeightIdx = -1;
if(MinIdx == -1 &&
MaxIdx == -1)
{
for(int Idx = 0;
Idx < FlowerIdx;
++Idx)
{
if(Heights[FlowerIdx] > Heights[Idx])
{
BestHeightIdx = Idx;
break;
}
}
if(BestHeightIdx == -1)
{
BestHeightIdx = FlowerIdx;
}
}
int SwapToIdx = -1;
if((MaxIdx == -1 && MinIdx != -1) ||
(MinIdx == -1 && MaxIdx != -1) ||
(MaxIdx != -1 && MinIdx != -1 && MaxIdx == MinIdx))
{
SwapToIdx = (MinIdx != -1) ? MinIdx : MaxIdx;
}
else if(BestHeightIdx != -1)
{
SwapToIdx = BestHeightIdx;
}
else
{
fprintf(stderr, "Spot-finding error:\n MinIdx: %d, MaxIdx: %d, BestHIdx: %d\n",
MinIdx, MaxIdx, BestHeightIdx);
exit(1);
}
SwapTo(FlowerIdx, SwapToIdx, Heights);
SwapTo(FlowerIdx, SwapToIdx, Blooms);
SwapTo(FlowerIdx, SwapToIdx, Wilts);
}
}
int
main(int argc, char *argv[])
{
int Heights0[] = {5,4,3,2,1};
int Blooms0[] = {1,1,1,1,1};
int Wilts0[] = {365,365,365,365,365};
int Heights1[] = {5,4,3,2,1};
int Blooms1[] = {1,5,10,15,20};
int Wilts1[] = {4,9,14,19,24};
int Heights2[] = {5,4,3,2,1};
int Blooms2[] = {1,5,10,15,20};
int Wilts2[] = {5,10,15,20,25};
int Heights3[] = {5,4,3,2,1};
int Blooms3[] = {1,5,10,15,20};
int Wilts3[] = {5,10,14,20,25};
int Heights4[] = {1,2,3,4,5,6};
int Blooms4[] = {1,3,1,3,1,3};
int Wilts4[] = {2,4,2,4,2,4};
int Heights5[] = {3,2,5,4};
int Blooms5[] = {1,2,11,10};
int Wilts5[] = {4,3,12,13};
int *AllHeights[] = {Heights0, Heights1, Heights2, Heights3, Heights4, Heights5};
int *AllBlooms[] = {Blooms0, Blooms1, Blooms2, Blooms3, Blooms4, Blooms5};
int *AllWilts[] = {Wilts0, Wilts1, Wilts2, Wilts3, Wilts4, Wilts5};
int AllFlowerCounts[] = {5, 5, 5, 5, 6, 4};
printf("\n");
for(int Idx = 0;
Idx < 6;
++Idx)
{
int *Heights = AllHeights[Idx];
int *Blooms = AllBlooms[Idx];
int *Wilts = AllWilts[Idx];
int FlowerCount = AllFlowerCounts[Idx];
printf("Test %d\n", Idx);
Order(Heights, Blooms, Wilts, FlowerCount);
printf("{ ");
for(int Idx = 0;
Idx < FlowerCount;
++Idx)
{
printf("%d", Heights[Idx]);
if(Idx != (FlowerCount - 1))
{
printf(", ");
}
}
printf(" }\n\n");
}
}
EDIT: This solution is god awful and I came up with a better one that's actually DP; it's as follows: for each flower, loop through all other flowers checking which ones it blocks; for those flowers it blocks, check for all the flowers it blocks, and so on until you get to a flower that doesn't block any other ones. Put that flower in a new array. Backtrack and put each flower before it in the next slot of that new array. If done for each flower, you will get an array full of flowers that don't block any others. You then put each flower as far forward as possible. The DP part of this solution is that sometimes you'll come across the same flower that has already been blocked by another flower previously and has already been put in the new array, so we skip that flower instead of chasing down the flowers it blocks.
I have got the implementation in c++. I have used a vector datatype to store the height, bloom and wilt respectively and then i sorted it w.r.t to height after which i took the flowers one by one and arranged them according to the values associated with them.
here is the code :-
#include<iostream>
#include<vector>
#include<utility>
#include<algorithm>
using namespace std;
bool comp(pair<int, pair<int,int> >& a,pair<int, pair<int,int> >& b ){
return (a.first > b.first);
}
bool justify(pair<int, pair<int,int> >& a,pair<int, pair<int,int> >& b, int k , int
j, vector<pair<int,pair<int,int> > >& v){
if(((b.second.first <= a.second.first) && (b.second.second>= a.second.first)) ||
((b.second.first <= a.second.second) && (b.second.second>= a.second.second)) ||
((b.second.first > a.second.first) && (b.second.second < a.second.second) )){
pair<int, pair<int,int> > temp = v[j];
int i = j-1;
while(i >= k){
v[i+1] = v[i];
i--;
}
v[k] = temp;
return true;
}
return false;
}
int main() {
vector<pair<int,pair<int,int> > > v;
int n,a,b,c;
cin>>n;
for(int i = 0;i < n;i++){
cin>>a>>b>>c;
v.push_back(make_pair(a,make_pair(b,c)));
}
sort(v.begin(), v.end(), comp);
for(int j = 1;j < n;j++){
for(int k = 0;k < j;k++){
bool res = justify(v[k],v[j], k, j, v);
if(res)
break;
}
}
cout<<"output"<<endl;
for(int i = 0;i < n;i++){
cout<<v[i].first<<" "<<v[i].second.first<<" "<<v[i].second.second<<endl;
}
return 0;
}
I came across this question in one Interview. Please help me in getting the solution.
Question is:
You have sorted rotatable array, i. e. the array contains elements which are sorted and it can be rotated circularly, like if the elements in array are [5,6,10,19,20,29] then rotating first time array becomes [29,5,6,10,19,20] and on second time it becomes [20,29,5,6,10,19] and so on.
So you need to find the smallest element in the array at any point. You won’t be provided with number times array is rotated. Just given the rotated array elements and find out the smallest among them. In this case output should be 5.
Method 1:
You can do this in O(logN) time.
Use a modified binary search to find the point of rotation which is an index i such that arr[i] > arr[i+1].
Example:
[6,7,8,9,1,2,3,4,5]
^
i
The two sub-arrays (arr[1], arr[2], .., arr[i]) and (arr[i+1], arr[i+2], ..., arr[n]) are sorted.
The answer is min(arr[1], arr[i+1])
Method 2:
When you split the sorted, rotated array into two halves (arr[1],..,arr[mid]) and (arr[mid+1],..,arr[n]), one of them is always sorted and the other always has the min. We can directly use a modified binary search to keep searching in the unsorted half
// index of first element
l = 0
// index of last element.
h = arr.length - 1
// always restrict the search to the unsorted
// sub-array. The min is always there.
while (arr[l] > arr[h]) {
// find mid.
mid = (l + h)/2
// decide which sub-array to continue with.
if (arr[mid] > arr[h]) {
l = mid + 1
} else {
h = mid
}
}
// answer
return arr[l]
The above algorihtm fails if data element is repeated like {8,8,8,8,8} or {1,8,8,8,8} or {8,1,8,8,8} or {8,8,1,8,8} or {8,8,8,8,1}
// solution pasted below will work all test cases :)
//break the array in two subarray and search for pattern like a[mid]>a[mid+1]
// and return the min position
public static int smallestSearch(int[] array,int start,int end)
{
if(start==end)
return array.length;
int mid=(start+end)/2;
if(array[mid]>array[mid+1])
return min(mid+1,smallestSearch(array,start,mid),smallestSearch(array,mid+1,end));
else
return min(smallestSearch(array,start,mid),smallestSearch(array,mid+1,end));
}
public static int min(int a,int b)
{
if(a==b)
return a;
else if(a<b)
return a;
else
return b;
}
public static int min(int a,int b,int c)
{
if(a<c)
{
if(a<b)
{
return a;
}
else
{
return b;
}
}
else
{
if(b<c)
return b;
else
return c;
}
}
To Find the smallest number in the sorted rotated array:
using Binary search concept
public class RotatedSortedArrayWithoutDuplicates1 {
public static void main(String[] args) {
int[] a = { 4, 6, 8, 10, 34, 56, 78, 1, 3 };
System.out.println(findMin(a));
}
private static int findMin(int[] a) {
if (a.length == 0 || a == null) {
return -1;
}
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = start + (last - start) / 2;
int m = a[mid];
int s = a[start];
int l = a[last];
if (m > l) {
start = mid + 1;
}
if (m < l) {
last = mid;
} else {
last--;
}
} // while
if (a[start] > a[last]) {
return a[last];
} else {
return a[start];
}
}
}
But if you don't want to use Binary Search, then :
public class Abc {
public static void main(String[] args) {
int[] a = { 4, 5, 6, 7, 7, 8, 9, 1, 1, 2, 3, 3 };
System.out.println(findMin(a));
}
public static int findMin(int[] a) {
int min = a[a.length - 1];
for (int i = 0; i < a.length; i++) {
if (min > a[i]) {
min = a[i];
break;
}
}
return min;
}// findmin
}// end
Here is the code in Python:
def fix(a):
min = a[0]
for i in range(len(a)):
if(min > a[i]):
min = a[i]
break
return min
a = [2, 2,3,4,1,2]
print(fix(a))
My code is below with the algorithm as comments. Works even for the repeated elements.
//Find Min in Rotated Sorted Array
//Example: int array[10] = {7, 8, 9, 10, 11, 12, 3, 4, 5, 6};
// Min in the above array is 3
// Solution: Recursively search (Modified binary search) for the Pivot where is the smallest Element is present
// Algorithm:
// 1) Find the Mid of the Array
// 2) call the recursive function on segment of array in which there is a deviation in the order
// If (A[low] > A[mid]) array segment in which deviation in the order present is (low, mid)
// If (A[low] < A[mid]) array segment in which deviation in the order present is (mid + 1, high)
// Time Complexity: O(logn)
// Space Complexity: is of the recursive function stack that is being used
#define MIN(x,y) (x) <= (y) ? (x): (y)
int MininRotatedSortedArray(int A[], int low, int high)
{
if(low > high)
return -1;
if(low == high - 1)
return MIN(A[low], A[high]);
int mid = low + (high - low)/2;
if(A[low] > A[mid])
return MininRotatedSortedArray(A, low, mid);
else if(A[low] < A[mid])
return MininRotatedSortedArray(A, mid + 1, high);
else
return A[mid];
}
This can be done in O(1) time best case, O(n) time worst case, and O(lg n) time on average.
For a rotated sorted array, if the first element in the array is less than the last element in the array, then the sorted array is not rotated (or rotated 0 position). The minimum element is simply the first element.
If the middle element is less than the last element, then the minimum element is in [first, middle].
If the middle element is greater than the last element, then the minimum element is in [middle + 1, last].
If the middle element is equal to the last element, then there are two sub-cases:
the first element is larger than the last element, in which case the minimum element is in [first, middle + 1];
the first element is equal to the last element, in which case it is inconclusive to reject either half of the array. Reduce to linear search. For example, for arrays such as [5,5,5,1,5] and [5,1,5,5,5], it is impossible by just examining the first, last and middle element (since they are all equal) which half of the array the minimum element lies.
I wrote the following code in C++ to solve this problem, which should handle all cases (empty array, repeated elements).
template <typename Iterator>
Iterator rotated_min(Iterator begin, Iterator end)
{
while (begin != end)
{
if (*begin < *(end - 1))
{
return begin;
}
Iterator mid = begin + (end - 1 - begin) / 2;
if (*mid < *(end - 1))
{
end = mid + 1;
}
else if (*mid > *(end - 1))
{
begin = mid + 1;
}
else
{
if (*begin > *(end - 1))
{
end = mid + 1;
++begin;
}
else
{
//reduce to linear search
typename ::std::iterator_traits<Iterator>::value_type min_value = *begin;
Iterator min_element = begin;
for (Iterator i = begin + 1; i != end; ++i)
{
if (*i < min_value)
{
min_value = *i;
min_element = i;
}
}
return min_element;
}
}
}
return begin;
}
Find Min index in circular sorted array
Example : [7,8,9,1,2,3,4,5,6]
int findMinIndex(int []a, int start, int end)
{
int mid = (start + end)/2;
if (start - end == 1)
if(a[start] < a[end])
return start;
else
return end;
if (a[mid] > a[end]){
return findMinIndex(a,mid,end);
}
else{
return findMinIndex(a,start,mid);
}
return -1; //Not found
}
In case any one needs it.. My implementation in java..
takes care of sorted/unsorted ascending//descending order usecases..
drawback is it will still perform log n steps to find min value in a perfectly sorted set with no rotation.
http://ideone.com/fork/G3zMIb
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
int [] a = {3,3,0,2,2,2,2,1,2,2,2,2,2,2,2,2,2};
System.out.println(recursiveSplit(a,0,a.length-1));
}
public static int findMin(int x, int y){
if(x<=y){
return x;
}else{
return y;
}
}
public static int recursiveSplit(int[] arr , int a , int b){
int mid = (int) Math.floor(a + (b-a)/2);
int h1_l = a;
int h1_u = mid;
int h2_l = mid+1;
int h2_u = b;
int x=0;
int y=0;
//single element
if(a==b){
return arr[a];
}
//adjacent positions
if(h1_u-h1_l==1){
x=findMin(arr[h1_u],arr[h1_l]);
}else{
//else split
x=recursiveSplit(arr,h1_l,h1_u);
}
if(h2_u-h2_l==1){
y=findMin(arr[h2_u],arr[h2_l]);
}else{
y=recursiveSplit(arr, h2_l,h2_u);
}
return findMin(x, y);
}
}
Errors/suggestions/failed usecases are welcomed
public int findMin(int[] num) {
return findMin(num, 0, num.length-1);
}
public int findMin(int[] num, int left, int right){
if(left==right) return num[left];
if(left+1==right) return Math.min(num[left], num[right]);
int mid = (left+right)/2;
if(num[mid]>num[right]){
return findMin(num,mid+1,right);
}else if(num[mid]<num[right]){
return findMin(num,left,mid);
}else{
if(num[mid]==num[left]){
return Math.min(findMin(num,left,mid), findMin(num,mid,right));
}else{
return findMin(num,left,mid);
}
}
}
The following algorithm takes log(n) time. Assuming the array has no duplicate.
public int findMin(int[] num) {
if(num.length == 0) return -1
int r = num.length-1, l = 0;
while(l<r){
if(num[l]<=num[r]) return num[l]; //when not rotated, return the left most value
int mid = (r+l)/2;
if(num[mid]<num[r]){
r = mid;
}else{
l = mid+1;
}
}
return num[l];
}
I did it using a slightly modified version of binary search. What I am doing here is I keep going left or right based on where the minimum could be. For example in an ascending array if the mid element is less than the left most element, its possible that the minimum is to the left. While recursing thru the array, I also keep track of the minimum. The recursion continues until the end and then the latest min is returned. This also works with repeated elements.
public static void main(String[] args) throws IOException {
int[] rotated = {6, 7, 8, 1, 2, 3, 4, 5};
int min = findMin(rotated);
System.out.println(min);//1
}
public static int findMin(int[] sorted) {
return findMinRecursively(sorted, sorted[0], 0, (sorted.length - 1));
}
private static int findMinRecursively(int[] sorted, int min, int leftIndex, int rightIndex) {
if (leftIndex > rightIndex) {
return min;
}
int midIndex = (leftIndex + rightIndex) / 2;
if (sorted[midIndex] < min) {
min = sorted[midIndex];
}
if (sorted[midIndex] < sorted[leftIndex]) {
return findMinRecursively(sorted, min, leftIndex, (midIndex - 1));
} else {
return findMinRecursively(sorted, min, (midIndex + 1), rightIndex);
}
}
Question : Find minimum in a sorted rotated array .
Solution 1 : Using Binary Search
class Test18 {
public static void main(String[] args) {
int[] a = { 5, 6, 7, 8, 9, 10, 1, 2, 3 };
System.out.println(findmin(a));
}
// find min in a sorted rotated array
private static int findmin(int[] a) {
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = start + (last - start) / 2;
if (a[mid] > a[last]) {
start = mid + 1;
}
if (a[mid] < a[last]) {
last = mid;
} else {
mid--;
}
} // while
if (a[start] > a[last]) {
return a[last];
} else {
return a[start];
}
}
}
def searchinrotatedarray(arr1,l,h):
if l>h:
return arr1[0]
if h==l:
return arr1[l]
mid=(l+h)//2
if mid<h and arr1[mid+1]<arr1[mid]:
return arr1[mid+1]
elif mid>l and arr1[mid-1]<arr1[mid]:
return arr1[mid]
elif arr1[mid]<arr1[h]:
return searchinrotatedarray(arr1,l,mid-1)
else:
return searchinrotatedarray(arr1,mid+1,h)
first if statement checks if even array is rotated at all. in that case first element is the min . if length of list is 1 then that element is min.
else if mid element is less than last element then continue to look in second half else look for the element in first half
//java program to find minimum element in a sorted array rotated
//about any pivot in O(log n) in worst case and O(1) in best case
class ArrayRotateMinimum {
public static void main(String str[]) {
// initialize with your sorted rotated array here
int array[] = { 9, 1, 2, 3, 4, 5, 6, 7, 8, };
System.out.println("Minimum element is: " + minimumElement(array));
}
static int minimumElement(int array[]) {
// variables to keep track of low and high indices
int low, mid, high;
// initializing variables with appropriate values
low = 0;
high = array.length - 1;
while (low < high) {
// mid is always defined to be the average of low and high
mid = (low + high) / 2;
if (array[low] > array[mid]) {
// for eg if array is of the form [9,1,2,4,5],
// then shift high to mid to reduce array size by half
// while keeping minimum element between low and high
high = mid;
} else if (array[mid] > array[high]) {
// this condition deals with the end case when the final two
// elements in the array are of the form [9,1] during the
// last iteration of the while loop
if (low == mid) {
return array[high];
}
// for eg if array is of the form [4,5,9,1,2],
// then shift low to mid to reduce array size by half
// while keeping minimum element between low and high
low = mid;
} else {
// the array has not been rotated at all
// hence the first element happens to be the smallest element
return array[low];
}
}
//return first element in case array size is just 1
return array[0];
}
}
This is my pythonic solution using recursion:
Time complexity is O(log(n)) & Space complexity: O(1)
class Solution(object):
def findMin(self, nums):
left = 0
right = len(nums) -1
mid = len(nums) // 2
if len(nums) == 0:
return -1
if len(nums) == 1:
return nums[left]
if len(nums) == 2:
return min(nums[left], nums[right])
if nums[left] < nums[right]:
return nums[left]
elif nums[mid] > nums[left]:
return self.findMin(nums[mid + 1: ])
elif nums[mid] < nums[left]:
return self.findMin(nums[: mid + 1])
Here is a very simple answer, it will work for all test cases:
int a[] = {5,6,7,1,2,3,4};
int a[] = {1,2,3};
int a[] = {3,2,1};
int a[] = {3,1,2};
int a[] = {2,2,2,2};
public class FindSmallestNumberInSortedRotatedArray {
public static void main(String[] args) {
int a[] = { 4, 5, 6, 7, 1, 2, 3 };
int j = a.length - 1;
int i = 0;
while (i < j) {
int m = (i + j) / 2;
if (a[m] < a[m + 1] && a[m] < a[m - 1]) {
System.out.println(a[m] + "is smallest element ");
break;
} else if (a[m] > a[m + 1] && a[m - 1] > a[m + 1]) {
i = m + 1;
} else {
j = m - 1;
}
}
if (i == j)
System.out.println(a[i] + " is smallest element");
}
Solution for both array with duplicate and not, with the recursive binary search approach.
Unique array
var min = (A, l, h) => {
if(l >= h) return A[l];
let m = Math.floor((l + h) / 2);
// as its unique
if(A[m] > A[h]) {
// go towards right as last item is small than mid
return min(A, m + 1, h);
} else if(A[m] > A[m - 1]) {
// go towards left as prev item is smaller than current
return min(A, l, m - 1);
} else {
// right and left is greater than current
return A[m];
}
}
/**
* #param {number[]} nums
* #return {number}
*/
var findMin = function(nums) {
// If array is rotated nums.length time or same as it is
if(nums[0] < nums[nums.length - 1]) return nums[0];
return min(nums, 0, nums.length - 1);
};
Array with duplicates
var min = (A, l, h) => {
if(l >= h) return A[l];
// traverse from left "and right" to avoid duplicates in the end
while(A[l] == A[l+1]) {
l++;
}
let m = Math.floor((l + h) / 2);
// as its unique
if(A[m] > A[h]) {
// go towards right as last item is small than mid
return min(A, m + 1, h);
} else if(A[m] >= A[m - 1]) {
// go towards left as prev item is smaller than current
return min(A, l, m - 1);
} else {
// right and left is greater than current
return A[m];
}
}
/**
* #param {number[]} nums
* #return {number}
*/
var findMin = function(nums) {
// If array is rotated nums.length time or same as it is
if(nums[0] < nums[nums.length - 1]) return nums[0];
return min(nums, 0, nums.length - 1);
};