My program is suppose to count how many times the data in my array changed from increase to decrease or vice versa. For example: {1,2,3,4,3,4}
changes twice as the first four elements are increasing then decrease o 3 (causing one change) and then increase back to four causing a second change.
The idea in my code was that every time greater or decrease changed to false it would count when it happened but I cannot get it to work.
Any help is greatly appreciated as I am really struggling with this!
unsigned count = 0;
bool greater = true;
bool decrease = true;
for (unsigned i = 0; i < elements; i++){
if (a[i + 1] > a[i]){
greater = true;
}
else
greater = false;
count++;
}
for (unsigned i = 0; i < elements; i++){
if (a[i + 1] < a[i]){
decrease = true;
}
else
decrease = false;
count++;
}
return count;
Your logic is wrong
you may do something like
enum class EDirection { none, decreasing, increasing};
std::size_t count_direction_changes(const std::vector<int>& v)
{
std::size_t res = 0;
EDirection direction = EDirection::none;
for (std::size_t i = 1; i != v.size(); ++i) {
const int diff = v[i] - v[i - 1];
switch (direction)
{
case EDirection::none: {
if (diff == 0) {
break;
}
direction = (diff > 0) ? EDirection::increasing : EDirection::decreasing;
break;
}
case EDirection::increasing: {
if (diff < 0) {
++res;
direction = EDirection::decreasing;
}
break;
}
case EDirection::decreasing: {
if (diff > 0) {
++res;
direction = EDirection::increasing;
}
break;
}
}
}
return res;
}
Demo
You must change your loops. First of all you should stop the loop at size-1. Because you are comparing with next element and you can go out of bounds if your for is running until elements instead of elements-1.
Furthermore, you have a logic issue. If you are using a boolean variable as flag, you should check if it's true or not before increasing your counter. And in case you increments your counter you must reset that flag. Something similar to down loop should work. Maybe there is some little mistake because I don't have anythin to test it now. But it should be something similar to this.
for (unsigned i = 0; i < elements-1; i++){
if (a[i + 1] > a[i]){
greater = true;
}
else{
greater = false;
}
if(greater){
count++;
greater = false;
}
}
This is a lot like Jarod42's, but seeing as I've already coded it will throw it out there. BTW, I use the slightly awkward v[n] < v[n - 1] so it's only necessary to implement operator< to apply the algo to a user-defined type (i.e. not operator> as well).
#include <iostream>
#include <vector>
template <typename T>
size_t changes(const std::vector<T>& v)
{
if (v.size() <= 2) return 0;
size_t count = 0;
enum { Increasing, Decreasing, Flat } last;
last = v[0] < v[1] ? Increasing : v[1] < v[0] ? Decreasing : Flat;
for (size_t i = 2; i < v.size(); ++i)
if (v[i - 1] < v[i])
{
if (last == Decreasing) ++count;
last = Increasing;
}
else if (v[i] < v[i - 1])
{
if (last == Increasing) ++count;
last = Decreasing;
}
return count;
}
int main()
{
std::cout << changes<int>({ 1, 3, 5, 4, 6 }) << '\n';
std::cout << changes<int>({ 3, 3, 5, 4, 6 }) << '\n';
std::cout << changes<int>({ 4, 3, 5, 4, 2, 2, 1 }) << '\n';
}
See it run here.
Here is another approach, similar to Tony's and Jarod's:
#include <vector>
#include <cassert>
#include <iostream>
size_t countTrendChanges(const std::vector<int>& a) {
if (a.size() < 3)
return 0;
int trend = 0;
size_t count = 0;
for (size_t i = 1; i != a.size(); ++i) {
int new_trend = (a[i-1] < a[i]) - (a[i] < a[i-1]);
if (new_trend == 0)
continue;
if (trend != 0 && new_trend != trend)
count++;
trend = new_trend;
}
return count;
}
int main() {
assert(countTrendChanges({}) == 0);
assert(countTrendChanges({1}) == 0);
assert(countTrendChanges({3,2,1}) == 0);
assert(countTrendChanges({1,2,3}) == 0);
assert(countTrendChanges({1,2,2,3}) == 0);
assert(countTrendChanges({3,2,1,2,3}) == 1);
assert(countTrendChanges({1,2,3,2}) == 1);
assert(countTrendChanges({2,1,1,2}) == 1);
assert(countTrendChanges({1,2,2,1}) == 1);
assert(countTrendChanges({1,2,3,4,3,4}) == 2);
}
Related
I want to compare two arrays. One of them is a subset of the other one. I want my function to return the minimum and equal gap between the numbers of the first subset array in the other array.
For example if I have
arr1 = 2,1,4,2,8,3
sub= 1,2,3
I want my function to return 1 because the mimimum gap between all this numbers are 1.
arr1 = 2,1,5,2,1,2,3
sub= 1,2,3
I want my function to return 0 because the mimimum gap between 1,2,3 in arr1 is 0
Here is the code I am trying to do: My code always return 0 can you help me understand why, and how can I solve this.
int gap(int* arr, int* sub, int sizeArr, int sizeSub)
{
int index = 0; int gap = 0; bool flag = true;
int i = -1;
for (int jump = 1; jump < sizeArr / sizeSub; jump++)
{
index = 0;
for (i = i +1; i < sizeArr; i++)
{
if (sub[index] == arr[i])
{
for (int j = i + jump, index = 1; j < sizeArr; j = j + jump, index++)
{
if (arr[j] != sub[index]) { flag = false; break; }
else if (arr[j] == sub[index] && index == sizeSub) { flag = true; break; }
}
}
if (!flag) { break; }
else { gap = jump; break; }
}
}
return gap;
}
You initially took gap equally 0 but i think more suit to not store gap
and start iterate jump from 0. And return jump immediately after you found that it is suit.
Also i think that store index in such manner as you it is bad idea, because you code return wrong answer on
int a[] = { 2,1,4,4,2,8,5,3 };
int s[] = { 1,2,3 };
I think you should declare variable as soon as possible, otherwise there will be undesirable side effects.
So you code can be rewritten as
int gap(int *arr, int *sub, int sizeArr, int sizeSub)
{
for (int jump = 0; 1 + (jump + 1) * (sizeSub - 1) <= sizeArr; jump++) {
for (int start_index = 0; start_index + (jump + 1) * (sizeSub - 1) < sizeArr; start_index++) {
bool flag = true;
for (int index = 0; index < sizeSub; ++index) {
if (arr[start_index + index * (jump + 1)] != sub[index]) {
flag = false;
break;
}
}
if (flag) {
return jump;
}
}
}
return -1; //or some value that indicate that there is no answer
}
I have array(of numbers) with size N. I need to find minimum element which is unique,so if arr[5] ={1,2,3,1,2}, answer is 3.
I tried that with following code:
Int n = sizeof(arr)/sizeof(arr[0]);
sort(arr,arr + n);
for(int i = 0;i<N;i++){
for(int j = 0;j<N;j++){
if(arr[i] == arr[j]){
remove(arr,arr+n,i);
remove(arr,arr+n,j);
}
}
}
But problem is that this only work if I have 2 identical elements of arr.I could create if conditions for number of identical, but I can have 3 or 4 or 1000,so it will be pretty odd. So what is more elagant way to do this? Thank you in advance.
try this code, this uses an unordered map
int m = 2147483647;
int int_array[] = { 1,2,3,3,1,6,7,7,9 };
unordered_map<int, int> map;
for (int i = 0; i < sizeof(int_array) / sizeof(int_array[0]); i++) {
map[int_array[i]] = map[int_array[i]] + 1;
}
unordered_map<int, int>::iterator itr;
for (itr = map.begin(); itr != map.end(); itr++)
{
if (itr->second == 1) {
if (itr->first < m) {
m = itr->first;
}
}
}
printf("minimum unique is %d", m);
after sorting the array you can count the number of the dublicated members , if the member is unique then its count equals zero :
int main()
{
int arr[] = { 1, 2, 1, 3, 4, 1, 2 };
int n = sizeof(arr) / sizeof(int);
sort(arr, arr + n);
int count = 0;
int unique = -1;
for (int i = 0; unique == -1 && i < n - 1; ++i) {
if (arr[i] != arr[i + 1]) {
if (count==0)
unique = arr[i];
else
count = 0;
}
else {
count++;
}
}
if (count == 0 && unique ==-1)
unique = arr[n-1];
cout << unique;
return 0;
}
I propose the following code:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int arr[5] = { 1,2,3,2,1 };
int N = sizeof(arr) / sizeof(arr[0]);
sort(arr, arr + N);
int index = -1;
// Check first element is different comparing with second one.
// If the array is only one element, then first element is unique
if (N == 1 || arr[0] != arr[1]) {
index = 0;
}
else {
int i = 1;
while (i < N - 1 && index == -1) {
// Check number is different to previous and different to next value
if (arr[i - 1] != arr[i] && arr[i] != arr[i + 1]) {
index = i;
}
else
{
i++;
}
}
if (index == -1) {
// No found, check last element comparing with previous
if (arr[i - 1] != arr[i]) {
index = i;
}
}
}
if (index != -1) {
// Have found min value
cout << "Min not repeated value is " << arr[index] << endl;
}
else {
// All elements are repeated
cout << "No min value" << endl;
}
}
Once the array is sorted, I compare each value with previous and next value to check it is unique. But for first and last element are a special case.
Using what I said in the comments, with an extra bool.
int arr[] = { 1, 2, 1, 3, 4, 1, 2 };
int n = sizeof( arr ) / sizeof( int );
std::sort( arr, arr + n );
bool match = false;
for ( int i = 0; i < n; ++i ) {
if ( i == n - 1 || arr[i] != arr[i + 1] ) {
if ( match )
match = false;
else
return arr[i];
} else {
match = true;
}
}
return -1; // made up number in case all duplicates
If the two values are equal, then we know that we can't use that value again, so I set match to true. If they are not equal, then if it was already disqualified, I ignore it and set match back to false, otherwise, return that value.
There are more elegant ways to do this; this is just the simplest.
I have the C++ function to do. It works fine, but there are some cases where it works bad - "greedy problem".
My C++ code:
#include <vector>
#include <algorithm>
std::vector<int> ans;
std::vector<int> get_change(const std::vector<int> &denominations, int amount) {
//pure algo
std::vector<int> money = denominations;
std::vector<int> count;
ans.clear();
count.assign(money.size(), 0);
std::sort(money.begin(), money.end());
int summ = amount;
for (int i = count.size()-1; i >= 0; i--) {
count[i] = summ / money[i];
summ = summ % money[i];
if (summ==0)
break;
}
//ans generation
for (int i = 0; i < money.size(); i++)
for (int j = 0; j < count[i]; j++)
ans.push_back(money[i]);
return ans;
}
Greedy problem sample: get_change({ 1, 6, 9 }, 30) will return { 1, 1, 1, 9, 9, 9 }, but not { 6, 6, 9, 9 }.
The task is to improve this algorithm to get the same answer.
One possible approach is backtracking.
Backtracking is a general algorithm for finding all (or some) solutions to some computational problems, notably constraint satisfaction problems, that incrementally builds candidates to the solutions, and abandons a candidate ("backtracks") as soon as it determines that the candidate cannot possibly be completed to a valid solution. (Wikipedia)
Here, we try to determine the number of coins, for each coin.
The candidates are abandonned, as soon as the total number of coins is higher than the current optimal solution. Moreover, here, in a given situation (at step i), we directly calculate the maximum number of coins for coins[i], such that the total sum is not higher than the amount.
Here is a possible implementation:
#include <iostream>
#include <vector>
#include <algorithm>
std::vector<int> get_change(const std::vector<int>& denominations, int amount) {
std::vector<int> coins = denominations;
std::vector<int> n_coins(coins.size(), 0);
std::vector<int> n_coins_opt(coins.size(), 0);
int n = coins.size();
std::sort(coins.begin(), coins.end(), std::greater<int>());
int sum = 0; // current sum
int i = 0; // index of the coin being examined
int n_min_coins = amount / coins[n - 1] + 1;
int n_total_coins = 0;
bool up_down = true;
while (true) { // UP
if (up_down) {
n_coins[i] = (amount - sum) / coins[i]; // max number of coins[i]
sum += n_coins[i] * coins[i];
n_total_coins += n_coins[i];
if (sum == amount) {
if (n_total_coins < n_min_coins) {
n_min_coins = n_total_coins;
n_coins_opt = n_coins;
}
up_down = false;
sum -= n_coins[i] * coins[i];
n_total_coins -= n_coins[i];
n_coins[i] = 0;
i--;
}
else {
if (i == (n - 1) || (n_total_coins >= n_min_coins)) { // premature abandon
sum -= n_coins[i] * coins[i];
n_total_coins -= n_coins[i];
n_coins[i] = 0;
up_down = false;
i--;
}
else {
i++;
}
}
}
else { // DOWN
if (i < 0) break;
if (n_coins[i] == 0) {
if (i == 0) break;
i--;
}
else {
sum -= coins[i];
n_coins[i] --;
n_total_coins--;
i++;
up_down = true;
}
}
}
std::vector<int> ans;
for (int i = 0; i < coins.size(); i++)
for (int j = 0; j < n_coins_opt[i]; j++)
ans.push_back(coins[i]);
return ans;
}
int main() {
std::vector<int> coins = { 1, 6, 9 };
int amount = 30;
auto n_coins = get_change(coins, amount);
for (int i = 0; i < n_coins.size(); i++)
std::cout << n_coins[i] << " ";
std::cout << "\n";
return 1;
}
This is a dynamic programming problem.
import java.util.*;
import java.lang.*;
import java.io.*;
class Solution{
public static void main (String[] args) throws java.lang.Exception{
System.out.println(getChange(new int[]{1,6,9},30));
System.out.println(getChange(new int[]{1},3));
System.out.println(getChange(new int[]{4,20,500},450));
}
private static List<Integer> getChange(int[] denominations,int amount){
Arrays.sort(denominations);
List<Integer> ans = new ArrayList<>();
if(amount <= 0 || denominations[0] > amount) return ans;
int[][] dp = new int[amount + 1][2];
for(int i=0;i<denominations.length;++i){
if(denominations[i] > amount) break;
dp[denominations[i]][0] = 1;
dp[denominations[i]][1] = 0;
for(int j=denominations[i] + 1;j<=amount;++j){
if(dp[j-denominations[i]][0] > 0 && (dp[j][0] == 0 || dp[j-denominations[i]][0] + 1 < dp[j][0])){
dp[j][0] = dp[j-denominations[i]][0] + 1;
dp[j][1] = j-denominations[i];
}
}
}
if(dp[amount][0] > 0){
while(dp[amount][0] != 0){
ans.add(amount - dp[amount][1]);
amount = dp[amount][1];
}
}
return ans;
}
}
Demo: https://ideone.com/2fYg4F
Algorithm:
This is similar to coin change problem.
We first sort the numbers in the array for uniform computation.
Now, we iterate on all array elements and make each array element loop over all possible amounts from that element till final amount.
Now, we can make amount j(which is a sum) only if we have made sum j - denominations[i].
While doing so, we also check for minimum number of coins needed. If amount j with current denominations[i] needs lesser coins than the current value stored in dp[j][0], then we update the answer in dp[j] accordingly.
In the end, we just loop over the exact coins needed and return the answer.
What is dp[][]:
It's just a simple 2D array where the 0th column keeps track of minimum number of coins
needed in it's first index and 2nd index has the previous coin index that give it the
minimal value.
The 2nd index in dp[][] would ease out the calculation to find the exact coin value as we would have to just do amount - dp[amount][1] to get the coin value.
In the end, we just do a check of dp[amount][0] value. If it's value is 0, we don't have a solution, else we compute it.
I am adaptated vivek_23's dynamic solution to required C++ language.
std::vector<int> get_change2(const std::vector<int>& coins, int amount) {
std::vector<int> denominations = coins;
std::sort(denominations.begin(), denominations.end());
std::vector<int> ans;
if (amount <= 0 || denominations[0] > amount)
return ans;
int** dp = new int* [amount + 1];
for (int i = 0; i < amount + 1; i++) {
dp[i] = new int[2];
dp[i][0] = 0;
dp[i][1] = 0;
}
for (int i = 0; i < denominations.size(); i++) {
if (denominations[i] > amount) break;
dp[denominations[i]][0] = 1;
dp[denominations[i]][1] = 0;
for (int j = denominations[i] + 1; j <= amount; ++j) {
if (dp[j - denominations[i]][0] > 0 && (dp[j][0] == 0 || dp[j - denominations[i]][0] + 1 < dp[j][0])) {
dp[j][0] = dp[j - denominations[i]][0] + 1;
dp[j][1] = j - denominations[i];
}
}
}
if (dp[amount][0] > 0) {
while (dp[amount][0] != 0) {
ans.push_back(amount - dp[amount][1]);
amount = dp[amount][1];
}
}
return ans;
}
This problem which is similar to another that I solved here is giving me a wrong answer even though the algorithm works on the sample case.I have initialized all the variables this time and it works on a modified version of my previous algorithm.
#include <iostream>
int main() {
int n;
std::cin >> n;
int arr[n];
for (int i = 0; i <n ;++i) {
std::cin >> arr[i];
}
int four_count = 0, two_count = 0, three_long=0, one_long = 0 , max1_long = 0 ,max3_long = 0,a_depth = 0,max_depth = 0;
for (int i = 0; i < n; ++i) {
if (arr[i] == 3) {
if (arr[i+1] == 1) {
++a_depth;
if (a_depth > max_depth) {
max_depth = a_depth;
}
}
++four_count;
three_long += 2;
}
if (arr[i] == 1) {
if (arr[i+1] == 3) {
++a_depth;
if (a_depth > max_depth) {
max_depth = a_depth;
}
}
++two_count;
one_long += 2 ;
}
if (arr[i] == 2) {
if (arr[i+1] == 4 && i < n-1) {
--a_depth;
}
--two_count;
}
if (arr[i] == 4) {
if (arr[i+1] == 2 && i < n-1){
--a_depth;
}
--four_count;
}
if (four_count == 0 && two_count == 0) {
if (three_long >= one_long) {
if (three_long > max3_long) {
max3_long = three_long+one_long;
}
three_long = 0;
one_long = 0;
}
else {
if (one_long > max1_long) {
max1_long = one_long+three_long;
}
one_long = 0;
three_long = 0;
}
}
}
std::cout << max_depth*2 << " " << max1_long << " " << max3_long;
std::cout << "\n";
return 0;
}
Here is a link to the problem:
https://www.codechef.com/ZCOPRAC/problems/ZCO12003
In the below code:
for (int i = 0; i < n; ++i) {
if (arr[i] == 3) {
if (arr[i+1] == 1) {
when i reaches n-1, arr[i+1] becomes arr[n] resulting in an out-of-bounds memory access which will lead to undefined behaviour.
Let's say n is equal to 5. That means the array arr has the maximum index 4, because the first one is 0.
In your loop
for (int i = 0; i < n; ++i)
{ if (arr[i] == 3) {
if (arr[i+1] == 1) {
at some point i becomes n-1, so i == 4, then you try arr[i+1] meaning arr[5], which is out of bound.
Note that in the comment to P.Ws post, you tried if (arr[i+1] == 1 && i < n-1) to fix this. That won't work because there still is an arr[i+1] being executed. You could fix this by using
if(i < n-1) {
if(arr[i+1]) {
but that would mean an even deeper nesting of your ifs. You should probably rethink your approach to the given problem.
Edit: Are you sure you mean ++i and not i++?
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]