I'm making this function which counts the total amount of swaps and comparisons a quick sort function would do in total. When I run it, however, I get this error:
error C4700: uninitialized local variable 'quick' used
This happens in the 'if' statement for the base case listed in the function code below. SwapandComp is the name of the struct I am using to keep track of both the swaps and comparisons for the sorting, and partition is the function where we find where to separate the original array, and it is also where we count the swaps and comparisons.
int partition(int numbers[], int i, int k) {
int l = 0;
int h = 0;
int midpoint = 0;
int pivot = 0;
int temp = 0;
bool done = false;
// Pick middle element as pivot
midpoint = i + (k - i) / 2;
pivot = numbers[midpoint];
l = i;
h = k;
while (!done) {
// Increment l while numbers[l] < pivot
while (numbers[l] < pivot) {
++l;
totalComps++;
}
// Decrement h while pivot < numbers[h]
while (pivot < numbers[h]) {
--h;
totalComps++;
}
// If there are zero or one elements remaining,
// all numbers are partitioned. Return h
if (l >= h) {
totalComps++;
done = true;
}
else {
// Swap numbers[l] and numbers[h],
// update l and h
temp = numbers[l];
numbers[l] = numbers[h];
numbers[h] = temp;
totalSwaps++;
++l;
--h;
}
}
return h;
}
And now here is the quick sort function. As mentioned before, SwapandComp is the struct I used to keep track of both swaps and comparisons.
SwapandComp quicksort(int numbers[], int i, int k) {
SwapandComp quick;
int j = 0;
int z = 0;
// Base case: If there are 1 or zero elements to sort,
// partition is already sorted
if (i >= k) {
return quick;
}
// Partition the data within the array. Value j returned
// from partitioning is location of last element in low partition.
j = partition(numbers, i, k);
// Recursively sort low partition (i to j) and
// high partition (j + 1 to k)
quickSort(numbers, i, j);
quicksort(numbers, j + 1, k);
quick.swaps = totalSwaps;
quick.comps = totalComps;
return quick;
}
On the second line down, I write
SwapandComp quick;
to use for the quick sort struct. The error doesn't really make sense to me because I did declare 'quick' as a new struct to have the function return. Any help is appreciated! Thanks!
Initialize struct as bellow :
SwapandComp quick = { 0 };
SwapandComp quick;
Unless that type has a constructor, declaring a variable with it inside a function will leave it in an indeterminate state. Then returning it (without first initialising it, as per your base case) will cause exactly the issue you're seeing, a "using an uninitialised variable" warning.
You could just initialise the members when declaring it, such as with:
SwapandComp quick; quick.swaps = quick.comps = 0;
But a better way to do it is with a real initialisers, something like:
struct SwapAndComp {
unsigned swaps;
unsigned comps;
SwapAndComp(): swaps(0U) , comps(0U) {};
};
This method (initialisation as part of the class itself) allows you to properly create the structure without any users of it needing to worry about doing it correctly. And, if you want flexibility, you can simply provide a constructor that allows it while still defaulting to the "set to zero" case:
SwapAndComp(unsigned initSwaps = 0U, unsigned initComps = 0U)
: swaps(initSwaps) , comps(initComps) {};
Related
I have an unordered_map<int, int> which is updated at every step of a for loop. But at the end of the loop, I also need the lowest of the mapped values. Traversing it to find the minimum in O(n) is too slow. I know there exists MultiIndex container in boost but I can't use boost. What is the simplest way it can be done using only STL?
Question:
Given an array A of positive integers, call a (contiguous, not
necessarily distinct) subarray of A good if the number of different
integers in that subarray is exactly K.
(For example, [1,2,3,1,2] has 3 different integers: 1, 2, and 3.)
Return the number of good subarrays of A.
My code:
class Solution {
public:
int subarraysWithKDistinct(vector<int>& A, int K) {
int left, right;
unordered_map<int, int> M;
for (left = right = 0; right < A.size() && M.size() < K; ++right)
M[A[right]] = right;
if (right == A.size())
return 0;
int smallest, count;
smallest = numeric_limits<int>::max();
for (auto p : M)
smallest = min(smallest, p.second);
count = smallest - left + 1;
for (; right < A.size(); ++right)
{
M[A[right]] = right;
while (M.size() > K)
{
if (M[A[left]] == left)
M.erase(A[left]);
++left;
}
smallest = numeric_limits<int>::max();
for (auto p : M)
smallest = min(smallest, p.second);
count += smallest - left + 1;
}
return count;
}
};
Link to the question: https://leetcode.com/problems/subarrays-with-k-different-integers/
O(n) is not slow, in fact it is the theoretically fastest possible way to find the minimum, as it's obviously not possible to find the minimum of n items without actually considering each of them.
You could update the minimum during the loop, which is trivial if the loop only adds new items to the map but becomes much harder if the loop may change existing items (and may increase the value of the until-then minimum item!), but ultimately, this also adds O(n) amount of work, or more, so complexity-wise, it's not different from doing an extra loop at the end (obviously, the constant can be different - the extra loop may be slower than reusing the original loop, but the complexity is the same).
As you said, there are data structures that make it more efficient (O(log n) or even O(1)) to retrieve the minimum item, but at the cost of increased complexity to maintain this data structure during insertion. These data structures only make sense if you frequently need to check the minimum item while inserting or changing items - not if you only need to know the minimum only at the end of the loop, as you described.
I made a simple class to make it work although it's far from perfect, it's good enough for the above linked question.
class BiMap
{
public:
void insert(int key, int value)
{
auto itr = M.find(key);
if (itr == M.cend())
M.emplace(key, S.insert(value).first);
else
{
S.erase(itr->second);
M[key] = S.insert(value).first;
}
}
void erase(int key)
{
auto itr = M.find(key);
S.erase(itr->second);
M.erase(itr);
}
int operator[] (int key)
{
return *M.find(key)->second;
}
int size()
{
return M.size();
}
int minimum()
{
return *S.cbegin();
}
private:
unordered_map<int, set<int>::const_iterator> M;
set<int> S;
};
class Solution {
public:
int subarraysWithKDistinct(vector<int>& A, int K) {
int left, right;
BiMap M;
for (left = right = 0; right < A.size() && M.size() < K; ++right)
M.insert(A[right], right);
if (right == A.size())
return 0;
int count = M.minimum() - left + 1;
for (; right < A.size(); ++right)
{
M.insert(A[right], right);
while (M.size() > K)
{
if (M[A[left]] == left)
M.erase(A[left]);
++left;
}
count += M.minimum() - left + 1;
}
return count;
}
};
So for an assignment I've been asked to create a function that will generate an array of fibonacci numbers and the user will then provide an array of random numbers. My function must then check if the array the user has entered contains any fibonacci numbers then the function will output true, otherwise it will output false. I have already been able to create the array of Fib numbers and check it against the array that the user enters however it is limited since my Fib array has a max size of 100.
bool hasFibNum (int arr[], int size){
int fibarray[100];
fibarray[0] = 0;
fibarray[1] = 1;
bool result = false;
for (int i = 2; i < 100; i++)
{
fibarray[i] = fibarray[i-1] + fibarray[i-2];
}
for (int i = 0; i < size; i++)
{
for(int j = 0; j < 100; j++){
if (fibarray[j] == arr[i])
result = true;
}
}
return result;
}
So basically how can I make it so that I don't have to use int fibarray[100] and can instead generate fib numbers up to a certain point. That point being the maximum number in the user's array.
So for example if the user enters the array {4,2,1,8,21}, I need to generate a fibarray up to the number 21 {1,1,2,3,5,8,13,21}. If the user enters the array {1,4,10} I would need to generate a fibarray with {1,1,2,3,5,8,13}
Quite new to programming so any help would be appreciated! Sorry if my code is terrible.
It is possible that I still don't understand your question, but if I do, then I would achieve what you want like this:
bool hasFibNum (int arr[], int size){
if (size == 0) return false;
int maxValue = arr[0];
for (int i = 1; i < size; i++)
{
if (arr[i] > maxValue) maxValue = arr[i];
}
int first = 0;
int second = 1;
while (second < maxValue)
{
for (int i = 0; i < size; i++)
{
if (arr[i] == first) return true;
if (arr[i] == second) return true;
}
first = first + second;
second = second + first;
}
return false;
}
Here is a function that returns a dynamic array with all of the Fibonacci numbers up to and including max (assuming max > 0)
std::vector<size_t> make_fibs( size_t max ) {
std::vector<size_t> retval = {1,1};
while( retval.back() < max ) {
retval.push_back( retval.back()+*(retval.end()-2) );
}
return retval;
}
I prepopulate it with 2 elements rather than keeping track of the last 2 separately.
Note that under some definitions, 0 and -1 are Fibonacci numbers. If you are using that, start the array off with {-1, 0, 1} (which isn't their order, it is actually -1, 1, 0, 1, but by keeping them in ascending order we can binary_search below). If you do so, change the type to an int not a size_t.
Next, a sketch of an implementation for has_fibs:
template<class T, size_t N>
bool has_fibs( T(&array)[N] ) {
// bring `begin` and `end` into view, one of the good uses of `using`:
using std::begin; using std::end;
// guaranteed array is nonempty, so
T m = *std::max_element( begin(array), end(array) ); will have a max, so * is safe.
if (m < 0) m = 0; // deal with the possibility the `array` is all negative
// use `auto` to not repeat a type, and `const` because we aren't going to alter it:
const auto fibs = make_fibs(m);
// d-d-d-ouble `std` algorithm:
return std::find_if( begin(array), end(array), [&fibs]( T v )->bool {
return std::binary_search( begin(fibs), end(fibs), v );
}) != end(array);
}
here I create a template function that takes your (fixed sized) array as a reference. This has the advantage that ranged-based loops will work on it.
Next, I use a std algorithm max_element to find the max element.
Finally, I use two std algorithms, find_if and binary_search, plus a lambda to glue them together, to find any intersections between the two containers.
I'm liberally using C++11 features and lots of abstraction here. If you don't understand a function, I encourage you to rewrite the parts you don't understand rather than copying blindly.
This code has runtime O(n lg lg n) which is probably overkill. (fibs grow exponentially. Building them takes lg n time, searching them takes lg lg n time, and we search then n times).
The problem is to count the number of of values less than the value after index. Here is the code, but I can't understand how binary indexed tree has been used to do this?
#include <iostream>
#include <vector>
#include <algorithm>
#define LL long long
#define MOD 1000000007
#define MAXN 10
using namespace std;
typedef pair<int, int> ii;
int BIT[MAXN+1];
int a[MAXN+1];
vector< ii > temp;
int countSmallerRight[MAXN+1];
int read(int idx) {
int sum = 0;
while (idx > 0) {
sum += BIT[idx];
idx -= (idx & -idx);
}
return sum;
}
void update(int idx, int val) {
while (idx <= MAXN) {
BIT[idx] += val;
idx += (idx & -idx);
}
}
int main(int argc, const char * argv[])
{
int N;
scanf("%d", &N);
for (int i = 1; i <= N; i++) {
scanf("%d", &a[i]);
temp.push_back(ii(a[i], i));
}
sort(temp.begin(), temp.end());
countSmallerRight[temp[0].second] = 0;
update(1, 1);
update(temp[0].second, -1);
for (int i = 1; i < N; i++) {
countSmallerRight[temp[i].second] = read(temp[i].second);
update(1, 1);
update(temp[i].second, -1);
}
for (int i = 1; i <= N; i++) {
printf("%d,", countSmallerRight[i]);
}
putchar('\n');
return 0;
}
It would be helpful if someone could explain the working principal of the code.
to understand BIT this is one of the best links .
TC gives the full explaination of functions you used , but rest part is logic on how to use it .
For basic understanding :
ques: there are n heaps and in each heap initially there are 1 stones then we add stones from u to v…find how much stone are there in given heap.
the solution , with answer at each iteration is http://pastebin.com/9QJ589VR.
After you understand it , try to implement your question .
A better proof and motivation behind Binary Index trees can be found here.
https://cs.stackexchange.com/questions/10538/bit-what-is-the-intuition-behind-a-binary-indexed-tree-and-how-was-it-thought-a
Let's suppose, for example, that you want to store cumulative frequencies for a total of 7 different elements. You could start off by writing out seven buckets into which the numbers will be distributed
Change the representation from being an array of buckets to being a binary tree of nodes.
If you treat 0 to mean "left" and 1 to mean "right," the remaining bits on each number spell out exactly how to start at the root and then walk down to that number.
The reason that this is significant is that our lookup and update operations depend on the access path from the node back up to the root and whether we're following left or right child links. For example, during a lookup, we just care about the right links we follow. During an update, we just care about the left links we follow. This binary indexed tree does all of this super efficiently by just using the bits in the index.
If you don't care about the proof:
I googled BIT for dummies and found this
https://www.hackerearth.com/practice/data-structures/advanced-data-structures/fenwick-binary-indexed-trees/tutorial/
Property of a perfectly binary tree:
Given node n, the next node on the access path back up to the root in which we go right is given by taking the binary representation of n and removing the last 1.
Why isolate the last bit?
When we isolate the last bit, the index x only goes to indexes ((+/-)x&(-x)) whose update is neccesary or whose value is required during a lookup.
while query we go down the array and while update we go up the array.
For example query(6) is going to add sum at BIT[6] but also add sum at BIT[4] and BIT[0] because 6(110) - 2 = 4(100) - 4 = 0.
6(110)'s last bit is 2(10). Hence we do 6-2.
4(100)'s last bit is 4(100). Hence we do 4-4.
we stop when x==0.
Use the same logic for update just add, dont subtract.
One dry run should be enough to convince you that its really magical!
Also BIT is 1-based.
public static void update(int x, int val, int size){
//int k =x;
x++;
for (; x<size; x+= x&(-x))
BIT[x]+=val;
}
public static int query(int x){
//int k =x;
int toreturn =0;
for (; x >0; x-= x&(-x))
toreturn+=BIT[x];
return toreturn;
}
public static List<Integer> countSmaller(int[] nums) {
// will only work for positive numbers less that 7.
// I arbitrarily set the size to 7, my code my choice
int size = 7;
BIT = new int[size];
List<Integer> result = new ArrayList<Integer>();
for (int i =nums.length-1; i >=0; i--) {
int smaller_count = query(nums[i]);
result.add(smaller_count);
update(nums[i], 1, size);
}
Collections.reverse(result);
return result;
}
I'm stuck at an impass with this implementation. My n2 variable is being overwritten during the merging of the subarrays, what could be causing this? I have tried hard-coding values in but it does not seem to work.
#include <iostream>
#include <cstdlib>
#include <ctime> // For time(), time(0) returns the integer number of seconds from the system clock
#include <iomanip>
#include <algorithm>
#include <cmath>//added last nite 3/18/12 1:14am
using namespace std;
int size = 0;
void Merge(int A[], int p, int q, int r)
{
int i,
j,
k,
n1 = q - p + 1,
n2 = r - q;
int L[5], R[5];
for(i = 0; i < n1; i++)
L[i] = A[i];
for(j = 0; j < n2; j++)
R[j] = A[q + j + 1];
for(k = 0, i = 0, j = 0; i < n1 && j < n2; k++)//for(k = p,i = j = 1; k <= r; k++)
{
if(L[i] <= R[j])//if(L[i] <= R[j])
{
A[k] = L[i++];
} else {
A[k] = R[j++];
}
}
}
void Merge_Sort(int A[], int p, int r)
{
if(p < r)
{
int q = 0;
q = (p + r) / 2;
Merge_Sort(A, p, q);
Merge_Sort(A, q+1, r);
Merge(A, p, q, r);
}
}
void main()
{
int p = 1,
A[8];
for (int i = 0;i < 8;i++) {
A[i] = rand();
}
for(int l = 0;l < 8;l++)
{
cout<<A[l]<<" \n";
}
cout<<"Enter the amount you wish to absorb from host array\n\n";
cin>>size;
cout<<"\n";
int r = size; //new addition
Merge_Sort(A, p, size - 1);
for(int kl = 0;kl < size;kl++)
{
cout<<A[kl]<<" \n";
}
}
What tools are you using to compile the program? There are some flags which switch on checks for this sort of thing in e,.g. gcc (e.g. -fmudflap, I haven't used it, but it looks potehtially useful).
If you can use a debugger (e.g. gdb) you should be able to add a 'data watch' for the variable n2, and the debugger will stop the program whenever it detects anything writing into n2. That should help you track down the bug. Or try valgrind.
A simple technique to temporarily stop this type of bug is to put some dummy variables around the one getting trashed, so:
int dummy1[100];
int n2 = r - q;
int dummy2[100];
int L[5], R[5];
Variables being trashed are usually caused by code writing beyond the bounds of arrays.
The culprit is likely R[5] because that is likely the closest. You can look in the dummies to see what is being written, and may be able to deduce from that what is happening.
ANother option is to make all arrays huge, while you track down the problem. Again set values beyond the correct bounds to a known value, and check those values that should be unchanged.
You could make a little macro to do those checks, and drop it in at any convenient place.
I had used the similar Merge function earlier and it doesn't seem to work properly. Then I redesigned and now it works perfectly fine. Below is the redesigned function definition for merge function in C++.
void merge(int a[], int p, int q, int r){
int n1 = q-p+1; //no of elements in first half
int n2 = r-q; //no of elements in second half
int i, j, k;
int * b = new int[n1+n2]; //temporary array to store merged elements
i = p;
j = q+1;
k = 0;
while(i<(p+n1) && j < (q+1+n2)){ //merging the two sorted arrays into one
if( a[i] <= a[j]){
b[k++] = a[i++];
}
else
b[k++] = a[j++];
}
if(i >= (p+n1)) //checking first which sorted array is finished
while(k < (n1+n2)) //and then store the remaining element of other
b[k++] = a[j++]; //array at the end of merged array.
else
while(k < (n1+n2))
b[k++] = a[i++];
for(i = p,j=0;i<= r;){ //store the temporary merged array at appropriate
a[i++] = b[j++]; //location in main array.
}
delete [] b;
}
I hope it helps.
void Merge(int A[], int p, int q, int r)
{
int i,
j,
k,
n1 = q - p + 1,
n2 = r - q;
int L[5], R[5];
for(i = 0; i < n1; i++)
L[i] = A[i];
You only allocate L[5], but the n1 bound you're using is based on inputs q and p -- and the caller is allowed to call the function with values of q and p that allow writing outside the bounds of L[]. This can manifest itself as over-writing any other automatic variables, but because it is undefined behavior, just about anything could happen. (Including security vulnerabilities.)
I do not know what the best approach to fix this is -- I don't understand why you've got fixed-length buffers in Merge(), I haven't read closely enough to discover why -- but you should not access L[i] when i is greater than or equal to 5.
This entire conversation also holds for R[]. And, since *A is passed to Merge(), it'd make sense to ensure that your array accesses for it are also always in bound. (I haven't spotted them going out of bounds, but since this code needs re-working anyway, I'm not sure it's worth my looking for them carefully.)
i'm reading about the heap data structure, and i can't figure out when to use max heapify function and why.
I wrote a insert function that will always keep the heap a max-heap and i can't see when will max-heapify ever be used.
Can you please explain?
Thank you
this is my code:
int PARENT(int i) {
return i/2;
}
int LEFT(int i) {
return 2*i;
}
int RIGHT(int i ) {
return 2*i +1;
}
void max_heapify(int *v, int index, int heapsize) {
int largest;
int left = LEFT(index);
int right = RIGHT(index);
if (left<heapsize && v[left] > v[index])
largest = left;
else
largest = index;
if (right < heapsize && v[right] > v[largest])
largest = right;
if (largest !=index) {
v[index] = v[index] ^v[largest];
v[largest] = v[index] ^v[largest];
v[index] = v[index] ^v[largest];
max_heapify(v,largest,heapsize);
}
}
void insert(int *v, int * length, int value) {
v[++*length] = value;
int valuePos = *length;
int parent = PARENT(valuePos);
if (parent!=valuePos) {
while (v[parent] < v[valuePos]) {
v[parent] = v[parent] ^ v[valuePos];
v[valuePos] = v[parent] ^v[valuePos];
v[parent] = v[parent] ^ v[valuePos];
valuePos = parent;
parent = PARENT(valuePos);
}
}
}
The heapify algorithm should be used when turning an array into a heap. You could do that by inserting each array element in turn into a new heap, but that would take O(n lg n) time, while heapify does it in O(n) time.
max_heapify is expected to invoke on a regular array, to make it a heap. And insert does the maintenance work, which requires the array (v in your function) already being a heap.
The max-heapify function, as you call it, is a general heapify function (a heap can use any valid comparison function for sorting it's elements). It is intended to be used as an init function for constructing a heap from an array.
The complexities of functions for dealing with a heap (with their intented usages):
init (max-heapify): O(n) , used to initialize a heap from a sorted sequence (array) (max-sorted, in your case)
insert : O(lg n) , used to insert a single element in a heap (maintains the heap tree "sorted")
delete : O(lg n) , used to remove a "best" (max, in your case) element from a heap (maintains the heap tree "sorted")
But, since this question is tagged C++, you should also consider using a std::set from STL instead of implementing your own heap. Complexities of the considered operations are the same as for any heap implementation, and it can easily operate with any comparison function (either pre-written or user-written). Another advantage against a heap implementation is that it is a sorted container, and you can easily iterate trough all the elements in the sorted order (not just the first one) without destroying the structure.
The only problem with std::set is that it is a unique container - meaning, only 1 copy of an element with a same key can exist in it. But there is a solution for that also - std::multiset keeps sorted instances of multiple objects with the same key.
Also, depending on your required usage (it there is a lot of data associated with the search key), you might also want to try std::map or std::multimap.
If you want to make your own heap implementation, I would strongly suggest putting it in a separate class (or even a namespace) if your intention is to use C++ to the fullest. If you just intend to keep the implementation in the form it is, you should consider re-tagging the question to C
You need to insert the data in heap randomly like in array. Afterwards u can call the max heapify function to keep the property of a Max Heap. Here is my code
class max_heap{
private: // are the private members of class
int *arr;
int size;
int ind;
};
void max_heap::bubbledown(int *ar, int i)
{
int len = ind - 1;
int lt = 2 * i;
int rt = lt + 1;
while (lt <= len && rt <= len)
{
if (arr[i] > arr[lt] && arr[i] > arr[rt])
break;
else if (ar[lt] > ar[rt])
{
if (ar[i] < ar[lt]){
swap(ar[i], ar[lt]);
i = lt;
lt = 2 * i;
}
}
else if (ar[lt] < ar[rt])
{
if (ar[i] < ar[rt]){
swap(ar[i], ar[rt]);
i = rt;
rt = (2 * i)+1;
}
}
}
}
void max_heap::heapify()
{
int len = ind - 1;
for (int i = len; i >= 1 && (i/2) >= 1; i--)
{
if (arr[i] > arr[i/2])
{
swap(arr[i], arr[i/2]);
bubbledown(arr, i);
}
}
}