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;
The array can hold negative numbers. I've written this code using recursion. First I'm summing the first i elements and then I'm checking for each such sum if the rest of the array (starting from i + 1) can be divided with this sum.
It works for some cases but not for others. I've noticed that it doesn't work if there's a prime somewhere.
It works if I sort the array in descending order beforehand but I don't understand why.
In this case the output is 2, while it should be 0.
#include <iostream>
const int N = 5;
int tab[N] = {1, 2, 3, 3, 4};
// returns the number of partitions with a given sum (or 0 if it can't be partitioned)
int divisions(int tab[N], int p, int sum) {
if (N < 2) return 0;
if (p == N) {
return 1;
}
int s_sum = tab[p++];
while (s_sum != sum && p < N) {
s_sum += tab[p++];
}
if (s_sum == sum) {
return divisions(tab, p, sum) + 1;
} else {
return 0;
}
}
// creates all the possible sums and returns the greatest number of partitions where each partition sums up to some sum
int compareAllDivisions(int tab[N]) {
int maxResult = 0;
for (int i = 0; i < N; ++i) {
int sum = 0;
for (int j = 0; j <= i; ++j) {
sum += tab[j];
}
int result = divisions(tab, i + 1, sum);
if (maxResult < result) {
maxResult = result;
}
}
if (maxResult >= 2) {
return maxResult;
} else {
return 0;
}
}
int main() {
std::cout << compareAllDivisions(tab) << std::endl;
return 0;
}
It is because of return value of if (s_sum == sum) part.
It should be changed like below
if (s_sum == sum) {
int ret = divisions(tab, p, sum);
if(ret == 0) return 0;
else return ret + 1;
} else {
return 0;
}
Your return value of divisions is 0 when can't make and pos number when can make.
So, let's consider when 0 returns in there. It can't make at the back, but it will return pos number!
I have written this code after studying from Introduction to Algorithm. I am unable to find out what is the problem with the code. I have written the code for heapsort and it runs well. heap_extract_max() will return the maximum value. heap_increase_key() increase the priority of an element. Here I have written program for priority queue using singly linked list which runs well.
#include <iostream>
#include <vector>
#include <algorithm>
template<typename T>
void max_heapify(std::vector<T>& array, size_t index)
{
size_t largest;
size_t left = (2*index) + 1;
size_t right = left + 1;
if(left < array.size() && array[left] > array[index])
largest = left;
else
largest = index;
if(right < array.size() && array[right] > array[largest])
largest = right;
if(largest != index)
{
int tmp = array[index];
array[index] = array[largest];
array[largest] = tmp;
max_heapify(array, largest);
}
}
template<typename T>
void build_max_heap(std::vector<T>& array)
{
for(size_t i = (array.size()/2) - 1; i >= 0; i--)
max_heapify(array, i);
}
template<typename T>
T heap_maximum(std::vector<T>& array)
{
return array[0];
}
template<typename T>
T heap_extract_max(std::vector<T>& array)
{
if(array.size() < 0)
{
std::cerr << "Heap Underflow \n";
}
else
{
T max = array[0];
array[0] = array[array.size() - 1];
//array.size() = array.size() - 1;
max_heapify(array, 1);
return max;
}
}
template<typename T>
void heap_increase_key(std::vector<T>& array, size_t index, T value)
{
if(value < array[index])
{
std::cerr <<"New value is smaller than the current value\n";
return;
}
else
{
array[index] = value;
while(index > 0 && array[(index/2) - 1] < array[index])
{
std::swap(array[index], array[(index/2) - 1]);
index = (index/2) - 1;
}
}
}
template<typename T>
void max_heap_insert(std::vector<T>& array, T value)
{
array[array.size()] = -1;
heap_increase_key(array, array.size(), value);
}
int main()
{
std::vector<int> v({1, 2, 6, 3, 7});
build_max_heap(v);
std::cout << heap_extract_max(v)<<"\n";
for(size_t i = 0; i < v.size(); i++)
{
std::cout << v[i] << " ";
}
std::cout << "\n";
}
It is not showing any output. I am writing commands
$ g++ -std=c++11 priorityqueue.cpp -o priorityqueue
$ ./priorityqueue
Problem is with the below function what will be return for if case
because of that
Control may reach end of non-void function
template<typename T>
T heap_extract_max(std::vector<T>& array)
{
if(array.size() < 0)
{
std::cerr << "Heap Underflow \n";
}
else
{
T max = array[0];
array[0] = array[array.size() - 1];
//array.size() = array.size() - 1;
max_heapify(array, 1);
return max;
}
}
Add return -1 or anything else for if case
if(array.size() < 0)
{
std::cerr << "Heap Underflow \n";
return -1;
}
second problem
for(size_t i = (array.size()/2) - 1; i >= 0; i--)
Comparison of unsigned expression >= 0 is always true
Try changing to:(as suggested by Serge Rogatch)
for(int64_t i = (int64_t(array.size())/2) - 1; i >= 0; i--)
As well as there is problem with extracting it
Before change result was
7
2 3 6 1 2
Program ended with exit code: 0
Because of wrong handling of remove .Handled removed properly in below code
template<typename T>
T heap_extract_max(std::vector<T>& array)
{
if(array.size() < 0)
{
std::cerr << "Heap Underflow \n";
return -1;
}
else
{
T max = array[0];
array[0] = array[array.size() - 1];
array.erase(std::remove(array.begin(), array.end(), array[0]),
array.end());
array.shrink_to_fit();
max_heapify(array, 0);
return max;
}
}
After change
7
6 3 1 2
Program ended with exit code: 0
It seems your program enters an infinite loop or crashes. I see a problem here:
for(size_t i = (array.size()/2) - 1; i >= 0; i--)
Because i is unsigned, it is always i >= 0. Also, for array.size() <= 1, you initialize it with some large positive integer, because i tries to go negative, but size_t is never negative, so the number wraps.
Try changing to:
for(int64_t i = (int64_t(array.size())/2) - 1; i >= 0; i--)
Also you seem to confuse 0- and 1-based array indexing, and you should do array.pop_back() in place of //array.size() = array.size() - 1;. Furthermore, it seems you intended array[1] instead of array[0] here:
T max = array[0];
array[0] = array[array.size() - 1];
If you stick with 1-based indexing, you should place and keep a dummy element at index 0 in your array:
std::vector<int> v({/*dummy*/-1, 1, 2, 6, 3, 7});
Array size is never negative, so you don't need if(array.size() < 0) and what's in then clause.
Though 0-based indexing is more natural in C++ and heap can be implemented with it too. For this you would need to revise all the index arithmetic like:
size_t left = (2*index) + 1;
size_t right = left + 1;
and
array[(index/2) - 1]
Qus: Remove duplicates from Sorted Array
Given a sorted array, remove the duplicates in place such that each element appears only once and return the new length.
Note that even though we want you to return the new length, make sure to change the original array as well in place
Do not allocate extra space for another array, you must do this in place with constant memory.
I tried following code, can anyone help where I am going wrong??
#include<iostream>
#include<vector>
using namespace std;
int removeDuplicates(vector<int> &A) {
int m=A.size();
if(m<=1) return m;
vector<int> :: iterator i=A.begin();
vector<int> :: iterator j=A.begin()+1;
vector<int> :: iterator temp;
while(i!=A.end() && j!=A.end())
{
while(j!=A.end() && *i == *j)
{
temp=j;
j++;
A.erase(temp);
}
i=j;
j++;
}
return A.size();
}
int main()
{
vector<int> vec={0,0,0,0,0,0,0,4,4,7,7,7,7,9};
cout<<"ans="<<removeDuplicates(vec);
return 0;
}
When you increment j, then erase the element there, the elements starting at j+1 are moved down. You're skipping over an element by incrementing.
A better approach would be to simply copy the non-repeating elements from one iterator to the other and setting the new length at the end of the main loop. Your current approach is potentially O(n^2), too slow for practical use.
I think this is that you need. This func loops array from tail to head and counts same values. Then performs shift of already unique values on ununique one.
It doesn't change actual size of vector due process because it would probably involve reallocation of memory inside of vector.
int removeDuplicates(vector<int> &vec) {
int currentVal = vec.size() - 1;
int uniqueNumber = 0;
while (currentVal >= 0) {
++uniqueNumber;
int sameVal = currentVal;
while (sameVal > 0 && vec[sameVal - 1] == vec[currentVal])
--sameVal;
int shiftSize = uniqueNumber;
for (int k = 1; k < shiftSize; ++k) {
vec[sameVal + k] = vec[currentVal + k];
}
currentVal = sameVal - 1;
}
return uniqueNumber;
}
You are asked to use an array. Although vector is similar in many ways, it is not the same. Have a look at the example code below.
In addition you are asked to keep memory allocated the same. You cannot ensure that using vector, it's size can grow / shrink once you add / remove elements and when an element is removed the data in the array behind the vector will be reallocated and rewritten.
int main()
{
int arr[14] = {0,0,0,0,0,4,4,4,4,5,5,5,7,9};
int last_non_duplicate_index = 0;
int current_index = 0;
int size = 14;
int new_size = size;
bool is_last_value = false;
// you can use for interchangeably
while(!is_last_value)
{
current_index++; // move one position ahead
if(current_index < size) // out of bonds check
{
if(arr[last_non_duplicate_index] != arr[current_index]) // value at position of current index is different
{
last_non_duplicate_index++; // increase index of the last value which was not a duplicate by one
arr[last_non_duplicate_index] = arr[current_index]; // write at that index
// e.g. if last index was 0 -> increase it to 1 and rewrite whatsever under arr[1] (current index)
}
else // values are the same
{
new_size--; // devrease the size
}
}
else
{
is_last_value = true; // current_index >= size -> out of bonds
}
}
for (int i = 0; i < new_size; i++)
{
std::cout << "arr[" << i << "]" << " = " << arr[i] << std::endl;
}
std::cout << "New size: " << new_size << std::endl;
return 0;
}
#TC : O(n)
#SC : O(1)
def removeDuplicates(arr,n):
# If array has no elements or only one element, return n
if (n==0 and n==1):
return n
# arr = [1,2,2,3,4,4,4,5,5]
# When i = 0, j= 0 arr=[1,2,2,3,4,4,4,5,5], arr[0] != arr[1], hence arr[0] = arr[0] and j =1, Increment i
# When i = 1, j = 1 arr[j] =[1,2,2,3,4,4,4,5,5]. arr[1] == arr[2], hence increment i
# When i = 2, j = 1 arr[j] = [1,2,2,3,4,4,4,5,5] arr[2] != arr[3], hence arr[1] = arr[2] j = 2, increment i
# When i =3, j = 2 arr[j] = [1,2,3,3,4,4,4,5,5] arr[3] != arr[4], hence arr[2] = arr[3] and j = 3, Increment i
# When i = 4, j = 3 arr[j] =[1,2,3,3,4,4,4,5,5] arr[4] == arr[5], hence increment i
# When i = 5, j = 3 arr[j] = [1,2,3,3,4,4,4,5,5] arr[5] == arr[6], hence increment i
# When i = 6, j = 3 arr[j] = [1,2,3,4,4,4,4,5,5] arr[6] != arr[7], hence arr[3] = arr[6] and j = 4, Increment i
# When i = 7, j= 4 arr[j] = [1,2,3,4,4,4,5,5] arr[7] == arr[8], hence Increment i
# End of for loop
j = 0
for i in range(0,n-1):
if arr[i] != arr[i+1]:
arr[j] = arr[i]
j = j + 1
# Check for the last index element and copy it to a[j]. Increment the j and return j
# When j = 4 arr[j] = [1,2,3,4,5,4,4,5,5] increment j
# j = 5
arr[j] = arr[n-1]
j = j + 1
return j
if __name__=="__main__":
arr = [1,2,2,3,4,4,4,5,5]
#arr = [1,1,2]
#arr = [2,2,2,2,2]
n = len(arr)
print(removeDuplicates(arr,n))
You can do it using iterators like this:
#include<iostream>
#include<vector>
using namespace std;
int removeDuplicates(vector<int> &A) {
int m = A.size();
if(m <= 1) return m;
for (auto it1 = A.begin(); it1 != A.end(); it1++) {
for (auto it2 = it1 + 1; it2 != A.end();) {
if (*it1 == *it2) {
it2 = A.erase(it2);
} else {
it2++;
}
}
}
return A.size();
}
int main()
{
vector<int> vec = { 0, 0, 0, 0, 0, 0, 0, 4, 4, 7, 7, 7, 7, 9 };
cout << "ans=" << removeDuplicates(vec);
return 0;
}
I need to get the unique value from 2 int arrays
Duplicate is allowed
There is just one unique value
like :
int arr1[3]={1,2,3};
int arr2[3]={2,2,3};
and the value i want to get is :
int unique[]={1}
how can i do this?
im already confused in my 'for' and 'if'
this was not homework
i know how to merge 2 arrays and del duplicate values
but i alse need to know which array have the unique value
plz help me :)
and here is some code i did
int arr1[3]={1,2,3}
int arr2[3]={2,2,3}
int arrunique[1];
bool unique = true;
for (int i=0;i!=3;i++)
{
for (int j=0;j!=3;j++)
{
if(arr1[i]==arr2[j])
{
unique=false;
continue;
}
else
{
unique=true;
}
if(unique)
{
arrunique[0]=arr1[i]
break;
}
}
cout << arrunique[0];
Assuming:
You have two arrays of different length,
The arrays are sorted
The arrays can have duplicate values in them
You want to get the list of values that only appear in one of the arrays
including their duplicates if present
You can do (untested):
// Assuming arr1[], arr2[], and lengths as arr1_length
int i = 0,j = 0, k = 0;
int unique[arr1_length + arr2_length];
while(i < arr1_length && j < arr2_length) {
if(arr1[i] == arr2[j]) {
// skip all occurrences of this number in both lists
int temp = arr1[i];
while(i < arr1_length && arr1[i] == temp) i++;
while(j < arr2_length && arr2[j] == temp) j++;
} else if(arr1[i] > arr2[j]) {
// the lower number only occurs in arr2
unique[k++] = arr2[j++];
} else if(arr2[j] > arr1[i]) {
// the lower number only occurs in arr1
unique[k++] = arr1[i++];
}
}
while(i < arr1_length) {
// if there are numbers still to read in arr1, they're all unique
unique[k++] = arr1[i++];
}
while(j < arr2_length) {
// if there are numbers still to read in arr2, they're all unique
unique[k++] = arr2[j++];
}
Some alternatives:
If you don't want the duplicates in the unique array, then you can skip all occurrences of this number in the relevant list when you assign to the unique array.
If you want to record the position instead of the values, then maintain two arrays of "unique positions" (one for each input array) and assign the value of i or j to the corresponding array as appropriate.
If there's only one unique value, change the assignments into the unique array to return.
Depending on your needs, you might also want to look at set_symmetric_difference() function of the standard library. However, its treatment of duplicate values makes its use a bit tricky, to say the least.
#include <stdio.h>
#include <stdlib.h>
int cmp ( const void *a , const void *b )
{
return *(int *)a - *(int *)b;
}
int main()
{
int arr1[5] = {5,4,6,3,1};
int arr2[3] = {5, 8, 9};
int unique[8];
qsort(arr1,5,sizeof(arr1[0]),cmp);
printf("\n");
qsort(arr2,3,sizeof(arr2[0]),cmp);
//printf("%d", arr1[0]);
int i = 0;
int k = 0;
int j = -1;
while (i < 5 && k < 3)
{
if(arr1[i] < arr2[k])
{
unique[++j] = arr1[i];
i++;
}
else if (arr1[i] > arr2[k])
{
unique[++j] = arr2[k];
k++;
}
else
{
i++;
k++;
}
}
//int len = j;
int t = 0;
if(i == 5)
{
for(t = k; t < 3; t++)
unique[++j] = arr2[t];
}
else
for(t = i; t < 5; t++)
unique[++j] = arr2[t];
for(i = 0; i <= j; i++)
printf("%d ", unique[i]);
return 0;
}
This is my codes,though there is a good answer .
I didn't realize the idea that know which array have the unique value.
I also think that the right answer that you chose didn't , either.
Here is my version of the algorithm for finding identical elements in sorted arrays on Python in C ++, it works in a similar way
def unique_array(array0 : (int), array1 : (int)) -> (int):
index0, index1, buffer = 0, 0, []
while index0 != len(array0) and index1 != len(array1):
if array0[index0] < array1[index1]:
buffer.append(array0[index0])
index0 += 1
elif array0[index0] > array1[index1]:
buffer.append(array1[index1])
index1 += 1
else:
index0 += 1; index1 += 1
buffer.extend(array0[index0 : len(array0)])
buffer.extend(array1[index1 : len(array1)])
return buffer