I'm trying to print the last level in a min heap. I thought I had code that works, but one of the test cases fail. In terms of the test cases, I only have access to how the output does not match.
Here is my code:
#include "MinHeap.h"
#include <math.h>
using std::log2;
vector<int> lastLevel(MinHeap & heap)
{
// Your code here
vector<int> leaves;
int capacity = pow(2, log2(heap.elements.size()) + 1) - 1;
for (unsigned leaf = capacity / 2; leaf < heap.elements.size(); leaf++) {
leaves.push_back(heap.elements[leaf]);
}
return leaves;
}
And here is the MinHeap class that goes along with it:
#include "MinHeap.h"
MinHeap::MinHeap(const vector<int> & vector)
{
int inf = numeric_limits<int>::min();
elements.push_back(inf);
elements.insert(elements.end(), vector.begin(), vector.end());
buildHeap();
}
MinHeap::MinHeap()
{
int inf = numeric_limits<int>::min();
elements.push_back(inf);
}
void MinHeap::buildHeap()
{
std::sort(elements.begin() + 1, elements.end());
}
void MinHeap::heapifyDown(int index)
{
int length = elements.size();
int leftChildIndex = 2 * index;
int rightChildIndex = 2 * index + 1;
if (leftChildIndex >= length)
return; // index is a leaf
int minIndex = index;
if (elements[index] > elements[leftChildIndex]) {
minIndex = leftChildIndex;
}
if ((rightChildIndex < length)
&& (elements[minIndex] > elements[rightChildIndex])) {
minIndex = rightChildIndex;
}
if (minIndex != index) {
// need to swap
int temp = elements[index];
elements[index] = elements[minIndex];
elements[minIndex] = temp;
heapifyDown(minIndex);
}
}
void MinHeap::heapifyUp(int index)
{
if (index < 2)
return;
int parentIndex = index / 2;
if (elements[parentIndex] > elements[index]) {
int temp = elements[parentIndex];
elements[parentIndex] = elements[index];
elements[index] = temp;
heapifyUp(parentIndex);
}
}
void MinHeap::insert(int newValue)
{
int length = elements.size();
elements.push_back(newValue);
heapifyUp(length);
}
int MinHeap::peek() const
{
return elements.at(1);
}
int MinHeap::pop()
{
int length = elements.size();
int p = -1;
if (length > 1) {
p = elements[1];
elements[1] = elements[length - 1];
elements.pop_back();
heapifyDown(1);
}
return p;
}
void MinHeap::print() const
{
if (elements.size() > 1) {
int length = elements.size();
cout << "[";
for (int i = 1; i < length - 1; i++) {
cout << elements[i] << ", ";
}
cout << elements[elements.size() - 1] << "]" << endl;
} else {
cout << "[ ]" << endl;
}
}
Here is the output I get showing one of the test cases fail:
tests.cpp:31: FAILED:
REQUIRE( s_lastLevel(h) == lastLevel(h) )
with expansion:
{ 1804289383 (0x6b8b4567), 1681692777 (0x643c9869) }
==
{ 1681692777 (0x643c9869) }
===============================================================================
test cases: 1 | 1 failed
assertions: 3 | 2 passed | 1 failed
I'm not sure why my initial approach is failing. Much help is appreciated.
It seems like the problem is in this line:
int capacity = pow(2, log2(heap.elements.size()) + 1) - 1;
What you are doing here is equivalent to:
int capacity = 2 * heap.elements.size() - 1;
What you instead want to do is get the index of the parent of the last element and increment by one as the starting position of your iteration. Since children of a node at i are at 2i and 2i+1, you can simply divide the index of the last node (n-1) by two and add one. You can check that this must be a leaf since its children would be at 2 * ((n-1)/2 + 1) and 2 * ((n-1)/2 + 1) + 1 which are both guaranteed equal or grater than n. So this will return all leaves:
int start = (heap.elements.size() - 1) / 2 + 1;
for (unsigned leaf = start; leaf < heap.elements.size(); leaf++) {
leaves.push_back(heap.elements[leaf]);
}
return leaves;
If it is just the last level you want, start at the largest power of two smaller than the index of the last element (n-1):
int start = 1 << (int)(log2(heap.elements.size()-1));
for (unsigned leaf = start; leaf < heap.elements.size(); leaf++) {
leaves.push_back(heap.elements[leaf]);
}
return leaves;
I need to insert 0 between two negative values in linked list. But my function doesn't work. What's wrong?
P. S. listLength passes information about length of linked list.
Insert function:
void insert(int new_value, int preceed_num)
{
struct List1* last;
struct List1 *brand_new;
brand_new = new(struct List1);
last = getAddress(preceed_num - 1);
brand_new -> Next = last -> Next;
last -> Next = brand_new;
brand_new -> Info = new_value;
amount++;
}
Inserting zero between two values function:
void insert_zero_unction()
{
int length = listLength();
int first, second;
for(int count = 1; count < length; count++)
{
first = getValue(count);
second = getValue(count + 1);
if(first < 0 && second < 0)
{
insert(0, first);
length++;
}
}
}
as #molbdnilo and #user4581301 said, traversing the list and using pointers in algorithm solved the problem. Here is re-written code:
void Zeroed_Stack_Function()
{
int length = listLength();
struct List1* first, *second;
int count = 1;
int to_past;
while(count <= length)
{
first = getAddress(count - 1);
second = getAddress(count);
if(first -> Info < 0 && second -> Info < 0)
{
insert(0, count);
}
length = listLength();
count++;
}
}
One of the functions I am doing uses a insertion sort for a two dimensional array with 2 rows and 12 columns. The first row is for student IDs, so there are 12 students total. The second row has the corresponding GPA for each student. I am not sure how to come up with an insertion sort to sort the GPA numbers in ascending order. Any help would be awesome!
I have this so far.
void insertionSort(double avg[][COLS])
{
int current = 1;
int last = COLS - 1;
int temp;
int walker;
int row = 1;
while (current <= last)
{
temp = avg[row][current];
walker = current - 1;
while (walker >= 0
&& temp < avg[row][walker])
{
avg[row][walker+1] = avg[row][walker];
walker = walker - 1;
}
avg[row][walker+1] = temp;
current = current + 1;
}
Your problem is that temp variable is declared as an int it should be double also you should swap the ids too
void insertionSort(double avg[][COLS])
{
int current = 1;
int last = COLS - 1;
double temp;//this was an int
int walker;
int row = 1;
while (current <= last)
{
temp = avg[row][current];
walker = current - 1;
while (walker >= 0
&& temp < avg[row][walker])
{
avg[row][walker+1] = avg[row][walker];
avg[row-1][walker+1] = avg[row-1][walker];//swap the id of two students
walker = walker - 1;
}
avg[row][walker+1] = temp;
avg[row-1][walker+1] = temp;
current = current + 1;
}
}
i'm trying to build a min-heap in an array from an array where the index corresponds to an ASCII value and the value at that index represents a frequency.
I then use these find min functions to retrieve the minimum value
int findMinIndex(int *x){
int a = findMaxValue(x);
int i = 0;
int index;
for(i = 0;i < 128;i++){
if(a > x[i] && x[i] != 0){
a = x[i];
index = i;
}
}
return index;
}
int findMinValue(int *x){
int a = findMaxValue(x);
int i = 0;
for(i = 0;i < 128;i++){
if(a > x[i] && x[i] != 0){
a = x[i];
x[i] = 0;
}
}
return a;
}
After i retrieve those two values, i attempt to enter them into an array of heap objects
class node{
public:
int occurances;
char val;
};
for some reason when i do this, it only seems to fill the array partially correctly then fills the rest with the max frequency repeatedly.
when i use cout to see the array i end up with this
heap[1] = 1
heap[2] = 2
heap[3] = 6
heap[4] = 8
heap[0] = 36
heap[0] = 36
heap[0] = 36
heap[0] = 36
i can't really figure out what this means, or why this is happening.
so how can i fix it to where i end up with a min heap in array form?
I have to find least common number from an int array , I have written code but it is not working properly ,
Here is my logic,
1. sort the array
2. get min common counter updated
3. get if all are unique
and the code below,
static int min_loc ; //minimum value location
static int min_cnt ;
int all_uniqFlag = true;
void leastCommon(int data[],int n)
{
int rcount = 0; //Repeated number counter
int mcount = n; // minimum repetetion counter;
// The array is already sorted we need to only find the least common value.
for(int i = 0 ; i < n-1 ; i++)
{
//Case A : 1 1 2 2 2 3 3 3 3 4 5 5 5 5 : result should be 4
//Case B : 1 2 3 4 5 6 7 (All unique number and common values so all values should be printed
// and )
//Case C : 1 1 2 2 3 3 4 4 (all numbers have same frequency so need to display all )
cout << "data[i] : " << data[i] << " data[i+1] : " << data[i+1] << "i = " << i << endl;
if(data[i] != data[i+1])
{
//mcount = 0;
//min_loc = i;
//return;
}
if(data[i] == data[i+1])
{
all_uniqFlag = false;
rcount++;
}
else if(rcount < mcount)
{
mcount = rcount;
min_loc = i ;//data[i];
}
}
min_cnt = mcount;
}
As mentioned in the comment only Case B works and Case A and C is not working could you help me fix the issue ?
scan through the list
compare each element in the list with the last element in the out array
If the element matches, then increment its count by 1
If the element doesn't match then add the new element into out
array and increment index by 1
Once the scan is done, the out array will have all the distinct elementsout[][0] and their frequencies out[][1]
Scan through the frequency list (out[][1]) to find the lowest frequency
Finally do another scan through the element list out[][0] and print elements whose frequency matches with the lowest frequency
.
#include<stdio.h>
#include<stdlib.h>
#define N 8
int main()
{
//int data[N]={1,2,3,4,5,6,7};
int data[N]={1,1,2,2,3,3,4,4};
//int data[N]={1,1,2,2,2,3,3,3,3,4,5,5,5,5};
int out[N][2];
int i=0,index=0;
for(i=0;i<N;i++)
{
out[i][0]=0;
out[i][1]=0;
}
out[0][0] = data[0];
out[0][1]=1;
for(i=1;i<N;i++)
{
if(data[i] != out[index][0])
{
index++;
out[index][0] = data[i];
out[index][1] = 1;
}
else
{
out[index][1]++;
}
}
int min=65536;
for(i=0;i<N;i++)
{
if(out[i][1] == 0)
{
break;
}
if(out[i][1] < min)
{
min = out[i][1];
}
}
for(i=0;i<N;i++)
{
if(out[i][1] == min)
{
printf("%d\t",out[i][0]);
}
}
printf("\n");
}
You can use a map for this:
#include <string>
#include <map>
#include <iostream>
typedef std::map<int, int> Counter;
void leastCommon(int data[],int n) {
Counter counter;
int min = n;
for (int i = 0; i < n; i++)
counter[data[i]]++;
for (Counter::iterator it = counter.begin(); it != counter.end(); it++) {
if (min > it->second) min = it->second;
}
for (int i = 0; i < n; i++) {
if (counter[data[i]] == min) {
std::cout << data[i] << std::endl;
counter[data[i]]++;
}
}
}
int main() {
int data[] = {1, 1,3,4,4,2,4,3,2};
leastCommon(data, 9);
return 0;
}
Approach is-
select 1st element from the sorted array, and while consecutive elements to it are same, store them in output[] until the loop breaks
store the frequency of element in leastFrequency
select next element, check with its consecutive ones and store them in same output[] until the loop breaks
check frequency of this with the leastFrequency
if same, do nothing (let these be added in the output[])
if less, clear output[] and store the element same no. of times
if more, change the effective output[] length to previous length before iterating for this element
similarly iterate for all distinct elements and finally get the result from output[] from 0 to effective length
void leastCommon(int data[], int len) {
if ( len > 0) {
int output[] = new int[len];
int outlen = 0; // stores the size of useful-output array
int leastFrequency = len; // stores the lowest frequency of elements
int i=0;
int now = data[i];
while (i < len) {
int num = now;
int count = 0;
do {
output[outlen] = now;
outlen++;
count++;
if((++i == len)){
break;
}
now = data[i];
} while (num == now); // while now and next are same it adds them to output[]
if (i - count == 0) { // avoids copy of same values to output[] for 1st iteration
leastFrequency = count;
} else if (count < leastFrequency) { // if count for the element is less than the current minimum then re-creates the output[]
leastFrequency = count;
output = new int[len];
outlen = 0;
for (; outlen < leastFrequency; outlen++) {
output[outlen] = num; // populates the output[] with lower frequent element, to its count
}
} else if (count > leastFrequency) {
outlen -= count; // marks outlen to its same frequent numbers, i.e., discarding higher frequency values from output[]
}
}
//for(int j = 0; j < outlen; j++) {
// print output[] to console
//}
}
}
Plz suggest for improvements.