This might be a weird question but I'm trying to figure out why the following code works.
It seems as though this code should be used where the heap elements index starts at 1 but it's starting at 0 and the sort is completed correctly.
I say that because the left child is calculated as (element*2) and the right child is (element*2 + 1). This would make the left child for the element with index 0 also have index 0.
#include <iostream>
using namespace std;
void siftDown(int numbers[], int root, int bottom) {
int done, maxChild, temp;
done = 0;
while ((root*2 <= bottom) && (!done)) {
if (root*2 == bottom)
maxChild = root * 2;
else if (numbers[root*2] > numbers[root*2 + 1])
maxChild = root * 2;
else
maxChild = root * 2 + 1;
if (numbers[root] < numbers[maxChild]) {
temp = numbers[root];
numbers[root] = numbers[maxChild];
numbers[maxChild] = temp;
root = maxChild;
} else {
done = 1;
}
}
}
void heapSort(int numbers[], int n) {
int i, temp;
for (i = n/2; i >= 0; i--) {
siftDown(numbers, i, n - 1);
}
for (i = n-1; i >= 1; i--) {
temp = numbers[0];
numbers[0] = numbers [i];
numbers [i] = temp;
siftDown(numbers, 0, i-1);
}
}
int main() {
int cases;
int n;
int count;
cin >> cases;
for (int i=0; i < cases; i++) {
cin >> n;
int array[n];
for (int j=0; j < n; j++) {
cin >> array[j];
}
heapSort(array, n);
for (int k=0; k < n; k++) {
cout << array[k];
}
cout << endl;
}
}
For the case when root = 0, there are two sub-cases: numbers[0] > numbers[1], or not. In the first, maxchild is set to 0. The next "if" clause - effectively "numbers[0] < numbers[0]" - necessarily evaluates to false, and so "done" is set to 1 and the loop terminates.
If numbers[1] >= numbers[0], then maxchild is set to 1. The next clause becomes "numbers[0] < numbers[1]" which may be true or may be false if numbers[0] == numbers[1]. If it is false, the loop terminates as before. If it is true, numbers[0] and numbers[1] are swapped - thus the larger number correctly moves to the top of the heap - and root becomes 1, the loop continues and in this case you understand how it works.
I think it's easiest to consider this case as a heap where the root only has one child (and all other nodes have two children as normal).
Related
Given an array of integers and a number k, write a function that returns true if given array can be divided into pairs such that sum of every pair is divisible by k.
This code is producing correct results for all test cases except one I cannot find the glitch in it.
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
int arr[n];
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
int k;
cin >> k;
int flag[n] = {0};
int p = 0;
int q = 0;
if (n % 2 != 0) {
cout << "False" << endl;
} else {
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if ((arr[i] + arr[j]) % k == 0 && flag[j] == 0) {
p = 1;
flag[j] = 1;
}
}
if (p == 0) {
q = 1;
cout << "False" << endl;
break;
}
}
if (q == 0) {
cout << "True" << endl;
}
}
}
return 0;
}
One of the big sources of bugs in code is messy code. So how do we clean up code? We modularize it. This means breaking up the code so that each portion of the code does one job well. Let's see what that looks like.
Function to check if something is divisible by k:
bool isDivisible(int number, int divisor) {
return number % divisor == 0;
}
Function to check all pairs:
The logic is as follows:
Take the first number in the list; call in n0.
For every remaining number n1, check if that plus the first number is divisible by k
When we find n1 such that n0 + n1 is divisible by k,
a. If the remaining numbers left over can also be split into divisible pairs, return true
b. Otherwise, continue searching
4.If we've searched through all the numbers, return false.
bool pairsDivisible(int* nums, int count, int k) {
if(count == 0) return true;
if(count % 2 != 0) return false; // count must be even
// 1.
int n0 = nums[0];
// 2.
for(int i = 1; i < count; i++) {
int n1 = nums[i];
// 3.
if(isDivisible(n0 + n1, k)) {
// Move the ith number so it's now nums[1]
std::swap(nums[1], nums[i]);
if(pairsDivisible(nums + 2, count - 2, k)) {
return true; // 3.a
} else {
// Reset the array
std::swap(nums[1], nums[i]);
}
}
}
return false;
}
So i was solving my homework, and i did this piece of code which is supposed to find the biggest difference beetween two prime numbers in the interval of [a,b], and i got "Process returned -1073741819 (0xC0000005)"
#include <iostream>
#include <vector>
#include <bitset>
using namespace std;
bitset <10000000>v;
int main()
{
for (int i = 2; i < 10000000; i++)
{
if (v[i] == 0)
{
for (int j = i * i; j < 10000000; j += i)
v[j] = 1;
}
}
int n, a, b, maxi = 0, mini = 0, smax = 0;
cin >> a >> b;
int poz = a;
while (v[poz] == 1)
poz++;
int prev = poz;
poz++;
while (v[poz] == 1 && poz < b)
poz++;
if (poz == b && v[b] == 1)
{
cout << -1; return 0;
}
int next = poz;
poz++;
while (poz <= b)
{
if (next - prev > smax)
{
smax = next - prev;
maxi = next;
mini = prev;
}
if (v[poz] == 0)
{
prev = next;
next = poz;
}
poz++;
}
cout << mini << " " << maxi;
return 0;
}
i expected 43 with 47
In your initialisation loop when i is 46349, i*i is 2,148,229,801, this is larger than fits inside a signed 32-bit integer so evaluates to -2,146,737,495. v[j] then causes the crash.
You should either modify your code to use a larger data type or set the limit for i to sqrt(10000000) rather than 10000000.
I'm guessing that i*i overflows when i is large, leading to a negative value for j and an access violation on v[j]=1;.
You have a potential segmentation fault on line v[j]=1; where j may exceed 10000000.
Please check your boundaries.
Homework: I'm just stumped as hell. I have algorithms set up, but I have no idea how to code this
Just to be clear you do not need arrays or to pass variables by reference.
The purpose of the project is to take a problem apart and using Top-Down_Design or scratch pad method develop the algorithm.
Problem:
Examine the numbers from 2 to 10000. Output the number if it is a Dual_Prime.
I will call a DualPrime a number that is the product of two primes. Ad where the two primes are not equal . So 9 is not a dual prime. 15 is ( 3 * 5 ) .
The output has 10 numbers on each line.
My Algorithm set-up
Step 1: find prime numbers.:
bool Prime_Number(int number)
{
for (int i = 2; i <= sqrt(number); i++)
{
if (number % 1 == 0)
return false;
}
return true;
}
Step 2: store prime numbers in a array
Step 3: Multiply each array to each other
void Multiply_Prime_Numbers(int Array[], int Size)
{
for (int j = 0; j < Size- 1; j++)
{
Dual_Prime[] = Arr[j] * Arr[j + 1]
}
}
Step 4: Bubble sort
void Bubble_Sort(int Array[], int Size) // Sends largest number to the right
{
for (int i = Size - 1; i > 0; i--)
for (int j = 0; j < i; j++)
if (Array[j] > Array[j + 1])
{
int Temp = Array[j + 1];
Array[j + 1] = Array[j];
Array[j] = Temp;
}
}
Step 5: Display New Array by rows of 10
void Print_Array(int Array[], int Size)
{
for (int i = 0; i < Size; i++)
{
cout << Dual_Prime[i] << (((j % 10) == 9) ? '\n' : '\t');
}
cout << endl;
}
I haven't learned dynamic arrays yet,
Although dynamic arrays and the sieve of Eratosthenes are more preferable, I tried to write minimally fixed version of your code.
First, we define following global variables which are used in your original implementation of Multiply_Prime_Numbers.
(Please check this post.)
constexpr int DP_Size_Max = 10000;
int DP_Size = 0;
int Dual_Prime[DP_Size_Max];
Next we fix Prime_Number as follows.
The condition number%1==0 in the original code is not appropriate:
bool Prime_Number(int number)
{
if(number<=1){
return false;
}
for (int i = 2; i*i <= number; i++)
{
if (number % i == 0)
return false;
}
return true;
}
In addition, Multiply_Prime_Numbers should be implemented by double for-loops as follows:
void Multiply_Prime_Numbers(int Array[], int Size)
{
for (int i = 0; i < Size; ++i)
{
for (int j = i+1; j < Size; ++j)
{
Dual_Prime[DP_Size] = Array[i]*Array[j];
if(Dual_Prime[DP_Size] >= DP_Size_Max){
return;
}
++DP_Size;
}
}
}
Then these functions work as follows.
Here's a DEMO of this minimally fixed version.
int main()
{
int prime_numbers[DP_Size_Max];
int size = 0;
for(int j=2; j<DP_Size_Max; ++j)
{
if(Prime_Number(j)){
prime_numbers[size]=j;
++size;
}
}
Multiply_Prime_Numbers(prime_numbers, size);
Bubble_Sort(Dual_Prime, DP_Size);
for(int i=0; i<DP_Size;++i){
std::cout << Dual_Prime[i] << (((i % 10) == 9) ? '\n' : '\t');;
}
std::cout << std::endl;
return 0;
}
The Sieve of Eratosthenes is a known algorithm which speeds up the search of all the primes up to a certain number.
The OP can use it to implement the first steps of their implementation, but they can also adapt it to avoid the sorting step.
Given the list of all primes (up to half the maximum number to examine):
Create an array of bool as big as the range of numbers to be examined.
Multiply each distinct couple of primes, using two nested loops.
If the product is less than 10000 (the maximum) set the corrisponding element of the array to true. Otherwise break out the inner loop.
Once finished, traverse the array and if the value is true, print the corresponding index.
Here there's a proof of concept (implemented without the OP's assignment restrictions).
// Ex10_TwoPrimes.cpp : This file contains the 'main' function. Program execution begins and ends there.
#include "pch.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void Homework_Header(string Title);
void Do_Exercise();
void Sieve_Of_Eratosthenes(int n);
void Generate_Semi_Prime();
bool Semi_Prime(int candidate);
bool prime[5000 + 1];
int main()
{
Do_Exercise();
cin.get();
return 0;
}
void Do_Exercise()
{
int n = 5000;
Sieve_Of_Eratosthenes(n);
cout << endl;
Generate_Semi_Prime();
}
void Sieve_Of_Eratosthenes(int n)
{
// Create a boolean array "prime[0..n]" and initialize
// all entries it as true. A value in prime[i] will
// finally be false if i is Not a prime, else true.
memset(prime, true, sizeof(prime));
for (int p = 2; p*p <= n; p++)
{
// If prime[p] is not changed, then it is a prime
if (prime[p] == true)
{
// Update all multiples of p
for (int i = p * p; i <= n; i += p)
prime[i] = false;
}
}
}
bool Semi_Prime(int candidate)
{
for (int index = 2; index <= candidate / 2; index++)
{
if (prime[index])
{
if (candidate % index == 0)
{
int q = candidate / index;
if (prime[q] && q != index)
return true;
}
}
}
return false;
}
void Generate_Semi_Prime()
{
for (int i = 2; i <= 10000; i++)
if (Semi_Prime(i)) cout << i << "\t";
}
Given an array "s" of "n" items, you have for each item an left value "L[i]" and right value "R[i]" and its strength "S[i]",if you pick an element you can not pick L[i] elements on immediate left of it and R[i] on immediate right of it, find the maximum strength possible.
Example input:
5 //n
1 3 7 3 7 //strength
0 0 2 2 2 //Left Value
3 0 1 0 0 //Right Value
Output:
10
Code:
#include < bits / stdc++.h >
using namespace std;
unsigned long int getMax(int n, int * s, int * l, int * r) {
unsigned long int dyn[n + 1] = {};
dyn[1] = s[1];
for (int i = 2; i <= n; i++) {
dyn[i] = dyn[i - 1];
unsigned long int onInc = s[i];
int left = i - l[i] - 1;
if (left >= 1) {
unsigned int k = left;
while ((k > 0) && ((r[k] + k) >= i)) {
k--;
}
if (k != 0) {
if ((dyn[k] + s[i]) > dyn[i]) {
onInc = dyn[k] + s[i];
}
}
}
dyn[i] = (dyn[i] > onInc) ? dyn[i] : onInc;
}
return dyn[n];
}
int main() {
int n;
cin >> n;
int s[n + 1] = {}, l[n + 1] = {}, r[n + 1] = {};
for (int i = 1; i <= n; i++) {
cin >> s[i];
}
for (int i = 1; i <= n; i++) {
cin >> l[i];
}
for (int i = 1; i <= n; i++) {
cin >> r[i];
}
cout << getMax(n, s, l, r) << endl;
return 0;
}
Problem in your approach:
In your DP table, the information you are storing is about maximum possible so far. The information regarding whether the ith index has been considered is lost. You can consider taking strength at current index to extend previous indices only if any of the previously seen indices is either not in range or it is in range and has not been considered.
Solution:
Reconfigure your DP recurrence. Let DP[i] denote the maximum answer if ith index was considered. Now you will only need to extend those that satisfy range condition. The answer would be maximum value of all DP indices.
Code:
vector<long> DP(n,0);
DP[0]=strength[0]; // base condition
for(int i = 1; i < n ; i++){
DP[i] = strength[i];
for(int j = 0; j < i ; j++){
if(j >= (i-l[i]) || i <= (j+r[j])){ // can't extend
}
else{
DP[i]=max(DP[i],strength[i]+DP[j]); // extend to maximize result
}
}
}
long ans=*max_element(DP.begin(),DP.end());
Time Complexity: O(n^2)
Possible Optimizations:
There are better ways to calculate maximum values which you might want to look into. You can start by looking into Segment tree and Binary Indexed Trees.
This is a question from a ZCO (Zonal Computing Olympiad; Indian IOI qualifying contest) paper.
Basically, it revolves around finding the number of distinct pairs of elements from a set of numbers whose sum does not exceed a certain value.
My solution works on all except the last test case (on a certain private server, the test case itself is not available), on which it exceeds the 3-second time limit by half a second.
Am I missing something, algorithmically? A few pointers would be nice.
Here is my code:
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> hardness;
hardness.reserve(n);
int temp;
for(int i = 1; i <= n; ++i) {
cin >> temp;
if (temp < k) {
hardness.push_back(temp);
}
}
sort(hardness.begin(), hardness.end());
int mx = hardness.back(); //Max element
int chewableCombinations = 0, cur = 0;
for(int i = 0; i < hardness.size() - 1; ++i) {
cur = hardness[i];
if(cur == 0 || cur + mx < k) {
chewableCombinations += hardness.size() - i - 1;
continue;
}
for(int j = i + 1; j < hardness.size(); ++j) {
if(cur + hardness[j] < k) {
++chewableCombinations;
} else break; //we've crossed the limit
}
}
cout << chewableCombinations << endl;
}
If hardness[i]+hardness[j] < k then hardness[i]+hardness[m] < k for all m < j.
You don't have to check them all.