Checking the neighbour values of arrays - c++

I have an array of numbers with length L, and I have to make the program check the sums of every array element with its preceding and following neighbors.
So, for example, if I have the array being {1, 2, 3}, the output for the 2nd element should be 6 because 1 + 2 + 3 = 6 and they are all neighbors.
If the chosen element is the first element in the array, its preceding neighbor is the last element of the array, and if the element is the last element in the array, the following neighbor is the first element of the array. So, in the {1, 2, 3} example, no matter what number you check, you always get 6, but if it were {1, 2, 3, 4} instead, the answer for the 3rd element would be 9 because 3 + 2 + 4 = 9.
I hope you understood how it should work.
The problem I am getting is that the output is out of control. I tried to check the array itself and it is completely normal. In the {1, 2, 3} example, I get an output of 7208681 and I don't know why.
#include <iostream>
using namespace std;
int main()
{
int total;
cin >> total;
int Bush[total]; //array of numbers
int temp, output = 0; //output variable and a container for the last resurt a.k.a temp
for (int i = 0; i <= total - 1; i++)
{
cin >> Bush[i]; //inputting the array elements
}
for (int i = 0; i < total; i++)
{
if (i == 0)
output = Bush[i] + Bush[i + 1] + Bush[total]; //checking if the loop checks the first number
if (i == total - 1)
output = Bush[i] + Bush[0] + Bush[i - 1]; //checking if the loop checks the first number
temp = output; //assigning the temp value to the current output value
output = Bush[i] + Bush[i + 1] + Bush[i - 1]; //assigning a new output value
if (temp > output)
output = temp; //checking values
}
cout << output << endl; //outputting
return 0;
}

When i = 0, the expression Bush[i-1] results in accessing an invalid location of the array (- 1).
Similarly, when i = total - 1 (last index of iteration), the expression Bush[i+1] gives you an index of total which is out of bounds of the array.

The last element of Bush is at index total -1, but you are accessing Bush[total] when i==0

At the end, there are many mistakes in your code, nonetheless, the problem with the if/else structure.
I would suggest you to use another inner loop, based on module operator that simplify the code a lot:
int max = 0;
for(int i = 0; i<total; i++)
{
output = Bush[i] + Bush[(i+1)%total] + Bush[(i-1+total)%total];
if(max < output) max = output;//checking the max
}
cout<<max<<endl;//outputting
that does the operation you required.
Hope this may help.

I think the below code would work
int main()
{
int total;
cout << "Enter Number of Elements " << endl;
cin>>total;
int Bush[total];//array of numbers
int temp = 0, output = INT_MIN; //output variable and a container for the last resurt a.k.a temp
cout << "Enter the Elements " << endl;
for(int i = 0; i<=total - 1; i++)
{
cin>>Bush[i];//inputting the array elements
}
for(int i = 0; i<total; i++)
{
if(i == 0)
temp = Bush[i] + Bush[i+1] + Bush[total -1];//checking if the loop checks the first number
else if(i == total - 1)
temp = Bush[i] + Bush[0] + Bush[i-1];//checking if the loop checks the first number
else
temp = Bush[i] + Bush[i+1] + Bush[i-1]; //assigning the temp value to the current output value
output = (temp > output)?temp:output;
}
cout<<output<<endl;//outputting
return 0;
}

Related

How can I reduce the time complexity of an algorithm in c++?

The following code takes in an integer t and then takes in 3 more integers t times and returns the maximum number of times you can subtract 1 from two different integers at the same time, whereas the program stops when there is only 1 integer above 0 remaining. I have solved the problem, but I want to reduce the time complexity of the code and I don't know how.
#include <bits/stdc++.h>
using namespace std;
int main() {
long long t, r, g, b, arr[1000], count = 0;
bool isMax=true;
cin >> t;
for (long long i = 0; i < t; i++) {
cin >> r >> g >> b;
arr[0] = r;
arr[1] = g;
arr[2] = b;
for (long long j = 0; j < 3; j++) {
for (long long k = 0; k < 2; k++) {
if (arr[k] > arr[k + 1]) {
long long a = arr[k];
long long b = arr[k + 1];
arr[k] = b;
arr[k + 1] = a;
}
}
}
count = 0;
if (arr[2] == 1) {
cout << 1 << endl;
} else if (arr[0] + arr[1] <= arr[2]) {
cout << arr[0] + arr[1] << endl;
} else {
while (arr[0] > 0) {
while (isMax && arr[0] > 0) {
arr[2]--;
arr[0]--;
count++;
if (arr[2] < arr[1]) {
isMax = false;
}
}
while (!isMax && arr[0] > 0) {
arr[1]--;
arr[0]--;
count++;
if (arr[1] < arr[2]) {
isMax = true;
}
}
}
while (arr[2] > 0 && arr[1] > 0) {
arr[2]--;
arr[1]--;
count++;
}
cout << count << endl;
}
}
}
How can I get the same output without using all these loops that increase the time complexity?
Edit: I don't want my code re-written for me, this is homework and all I want are tips and help so I can reduce the time complexity, which I don't know how to do.
Edit 2: In my algorithm, I sort the 3 numbers in ascending order, then I use a while loop to check if the smallest number (s/arr[0]) is > 0. After that, I use two more while loops to alternate between the largest and medium-size numbers (l/arr[2] and m/arr[1] respectively) and decrement from both variables s and l or m (alternating). When s becomes 0, that will mean I can just decrement l and m till one of them equals 0, and then I print the count variable (I increment count every time I decrement two of the variables).
Im not sure if i understood the problem correctly. But if i did you could optimize the algorithem the following way:
int count = 0;
int a = 20, b = 10, c = 21;
sort(a, b, c); // Function that sorts the numbers, so that a is the smallest and c is the largest
count += a; // count = 10
c -= a; // a = 10, b = 20, c = 11
if(c < b) {
float diff = b - c; // diff = 9
float distribute = diff / 2; // distribute = 4.5
count += b - ceil(distribute); // count = 25
}
else count += b;
You would have to this t times and then sum the count variables, resulting in a complexity of t.
Assuming your code is correct, you can examine exactly what your loops are doing, and look at them more mathematically.
if ( arr[2] == 1 ) {
cout << 1 << endl;
} else if ( arr[0] + arr[1] <= arr[2] ) {
cout << arr[0] + arr[1] << endl;
} else {
while ( arr[0] > 0 ) {
if ( arr[2] > arr[1] ) {
long long min = std::min( std::min( arr[0], arr[2] ), arr[2] - arr[1] + 1 );
arr[0] -= min;
arr[2] -= min;
count += min;
} else {
long long min = std::min( std::min( arr[0], arr[1] ), arr[1] - arr[2] + 1 );
arr[0] -= min;
arr[1] -= min;
count += min;
}
}
count += std::min( arr[2], arr[1] );
cout << count << endl;
}
Assuming your program was correct,t his produces the same results for all inputs I tried.
I'm not sure I understood the problem correctly but if you want to know the maximum number of times you can subtract 1 until hitting zero from two elements in a three element set, I believe the answer should be the same as finding the median element of the set. For example, if I have the set
10 20 30
The maximum amount of times I can subtract 1 is 20, if I always chose to subtract from the subset {20, 30}, while the minimum would be 10, if I always choose to subtract from the subset {10, 20}.
Hope this helps! (Assuming I didn't totally misunderstand the question ^_^ ")
Edit:
After the clarifying comment, I believe all you need to do is find the minimum between the sum of the non-maximum elements and the maximum element. Consider the following examples:
If you are given the set {80, 10, 210} for example, the answer to your problem is 90, because we can subtract 10 from the subset {80, 10}, leaving us with {70, 0, 210} where we can further subtract 70 from the subset {70, 210}, leaving us with {0,0,140}, where we can perform no more operations. We have performed 80+10 = 90 subtractions by 1 In this case, max = 210 and min+med = 90
On the other hand, the consider the set {2,2,2}. We can subtract 2 from the subset {2,2}, leaving us with {0,0,2}, where we can perform no more operations. In this case, we have performed 2 subtractions by 1 Max = 2 and min+med = 4
Last example: consider the set {2,3,5}. We can subtract 2 from the subset {2,3}, leaving us with {0,1,5}, where we can the subtract 1 from the subset {1,5}, resulting in {0,0,4}, where we can perform no more operations. In this case, we have performed 2+3=5 subtractions by 1 Max = 5 and min+med = 5
If you continue performing examples in this vein, you should be able to convince yourself that the solution is always going to be min(max, min+median).

Print the solution to maximum sum of non-consecutive elements in an array

I'm trying to display the elements in an array that sum up to a max number and no two elements are consecutive(adjacent).
I figured out how to calculate the max sum by maintaining an inclusive and exclusive sum of the array elements. Is there any optimized way to capture all the elements that constitute the max sum and display it in reverse order
Code :
int i_sum = tickets[0];
int e_sum = 0;
int new_sum = 0
int sum = 0;
for (int i = 1; i < n; i++)
{
new_sum = (i_sum > e_sum) ? i_sum : e_sum;
i_sum = e_sum + tickets[i];
e_sum = new_sum;
}
(i_sum >= e_sum) ? std::cout << "incl " << i_sum : std::cout << "excl " << e_sum;
For example :
n = 8
array = [ 100 , -3 , 200 , 50 , 400 , -7 , 20 , 80 ]
max sum = 780
output :
80,400,200,100
And if both the inclusive and exclusive sum is alike the output would be the one with the greater element set.
Case :
n = 4
array = [4 , 5 , 4, 3]
max sum = 8
output : 4, 4
Should I maintain two different arrays to hold all the possible values, or insert them one at a time on each pass?
Thanks in advance.
Yes, you could maintain two arrays and copy and swap them at each step. However, that is not optimal. It will make your algorithm O(n2).
std::vector<int> incl, excl;
if (tickets[0] > 0)
incl.push_back(tickets[0]);
for (int i = 1; i < n; i++)
{
std::vector<int> temp;
if (i_sum > e_sum) {
new_sum = i_sum;
} else {
new_sum = e_sum;
temp = excl;
}
i_sum = e_sum + tickets[i];
e_sum = new_sum;
excl.push_back(tickets[i]);
std::swap(incl, excl);
if (temp.size())
excl = temp;
}
incl or excl will contain your solution depending whichever is larger.
I've made a small optimization using std::swap to use move semantics that avoids copies but when e_sum > i_sum, we can't avoid copying temp to excl.
Instead, formulating the same problem using dynamic programming, you can accomplish this in O(n). The idea is similar. Either you include the current element and add to the solution to max sum of second previous element or you exclude the current element to have the solution for the previous element. Code as follows:
vector <int> dp(n);
vector <int> parent(n, 0);
if (tickets[0] > 0) {
dp[0] = tickets[0];
parent[0] = tickets[0];
}
if (tickets[1] > 0) {
dp[1] = tickets[1];
parent[1] = tickets[1];
}
for (int i = 2; i < n ; i++) {
if (dp[i-1] > tickets[i] + dp[i-2]) {
dp[i] = dp[i-1];
} else {
dp[i] = tickets[i] + dp[i-2];
parent[i] = tickets[i];
}
}
cout << "Max sum: " << dp[n-1] << endl;
for(int i = n - 1; i >= 0;) {
if (parent[i]) {
cout << parent[i] << ' ';
i = i - 2;
} else {
i--;
}
}
parent vector can be utilized to trace back the steps taken for the dynamic programming solution.
As a side note, the solution mentioned in your question is slightly incorrect. If the first element is negative, you'd get an unoptimal result.

Program crashes and does not display correct output

So I am working on a very "basic" problem for my c++ class and have encountered some errors. The problem is this
An interesting problem in number theory is sometimes called the “necklace problem.” This problem begins with two single-digit numbers. The next number is obtained by adding the first two numbers together and saving only the ones-digit. This process is repeated until the “necklace” closes by returning to the original two numbers. For example, if the starting numbers are 1 and 8, twelve steps are required to close the “necklace”:
18976392134718
Write a program that asks the user for two starting numbers, and then displays the sequence and the number of steps taken. The program output should look similar to:
Enter first number: 1
Enter ssecond number: 8
18976392134718
Your numbers required 12 steps.
What I have done is this:
` #include <iostream>
using namespace std;
int necklace(){
int firstNumber, secondNumber, total = 0, counter = 10, sumOfTwo, tempOne, tempTwo, count;
// 2 single digit numbers
// add first two numbers and save only one digit
// process keeps going until original numbers are found
cout << "Enter the first number: \n";
cin >> firstNumber;
cout << "Enter the second number: \n";
cin >> secondNumber;
sumOfTwo = firstNumber + secondNumber;
while (sumOfTwo >= 10){
sumOfTwo /= 10;
}
int numbersArray[] = {firstNumber, secondNumber, sumOfTwo};
for(int i = 0; i <= 20; i++){
tempOne = numbersArray[i + 1];
tempTwo = numbersArray[i + 2];
sumOfTwo = tempOne + tempTwo;
while (sumOfTwo >= 10){
sumOfTwo %= 10;
}
numbersArray[i + 3] = sumOfTwo;
total++;
if(tempOne == firstNumber && tempTwo == secondNumber){
break;
}
}
for(int i = 0; i < sizeof(numbersArray); i++){
cout << numbersArray[i];
}
cout << endl << "It took " << total << " steps to finish. \n";
return total;
}
int main() {
necklace();
}
`
The problem I am getting is that it will print out all the numbers except the original 2, for example if I use the example with 1 and 8, it will print out 189763921347 and then crash, when it is supposed to print out 18976392134718 with the 1 and 8 at the end of it. Any suggestions? Thanks!
int numbersArray[] = {firstNumber, secondNumber, sumOfTwo};
with three elements on the right hand side makes it an array of size 3. Meaning with indexes 0, 1 and 2.
The use of higher indexes will result in Undefined Behaviour (UB).
On the other hand:
for(int i = 0; i <= 20; i++){
tempOne = numbersArray[i + 1];
tempTwo = numbersArray[i + 2];
[...]
numbersArray[i + 3] = sumOfTwo;
with i up to 20 (included) indexes this very same array from 0 to 23 for the last line!
Next:
for(int i = 0; i < sizeof(numbersArray); i++){
sizeof(numbersArray) returns the size in bytes of the array:
sizeof(numbersArray) = 3 * sizeof(int)
Higher than 3, the real size of the array.
But, if you intend to print the values but not store them, you don't need an array. You just need to "exchange" the values like:
one two // beginning of loop
___|
| __ new_digit
| |
v v
one two // end of loop

Why does attempting to return in this function cause the program to crash in C++?

I am working through challenges on a site called CodeFights to help me learn C++ and improve my programming. One challenge was to write a program that would find the length of a specific sequence based on the zeroth element:
Element 0: 16
Element 1: 1^2 + 6^2 = 37
Element 2: 3^2 + 7^2 = 58
...
The sequence ends when an element is repeated.
This code is supposed to return the length of the sequence:
#include <cmath>
#include <iostream>
#include <vector>
int squareDigitsSequence(int a0) {
int counter = 0; //Counts number of elements
int temp = 0; //Stores current element
std::vector<int> sequence (1); //Stores sequence
sequence[0] = a0; //Stores first element in sequence
for (int i = 0;; i++) { //Loops until sequence finishes
counter += 1; //Increments counter
temp = 0; //Resets element storage
if (a0 < 10) { //If it is only 1 digit
temp += pow(a0, 2);
}
else if (a0 < 100 && a0 > 9) { //If it is 2 digits
temp += pow(a0 / 10, 2);
temp += pow(a0 % 10, 2);
}
else { //If it is 3 digits
temp += pow(a0 % 10, 2);
temp += pow(((a0 % 100) - (a0 % 10)) / 10, 2);
temp += pow(a0 / 100, 2);
}
for (int b = 0; b < counter; b++) { //Checks if the element has appeared before
if (temp == sequence[b]) {
return counter; //Crashes here.
}
}
sequence[i + 1] = temp; //Stores current element in sequence
a0 = temp; //Moves element to be checked to current element
}
return 0; //Would not accept the function without this
}
int main() {
std::cout << squareDigitsSequence(16);
return 0;
}
Attempting to run this causes the program to crash. I have attempted to debug, and also look for similar problems but no success. Help appreciated.
EDIT: The problem was that I created a vector with size (1), and tried to add more elements to it. Solution use .push_back() instead of [i + 1].
Thanks to everyone that answered, hope this can be useful to others in the future.
The crash is the result of an out-of-bound write in this line:
sequence[i + 1] = temp;
Since the vector is initialized with size 1 and never resized, you overflow the internal buffer and override some arbitrary memory location.
To avoid this problem, use vector::push_back, which will enlarge the vector if the internal buffer isn't large enough.

How can we find second maximum from array efficiently?

Is it possible to find the second maximum number from an array of integers by traversing the array only once?
As an example, I have a array of five integers from which I want to find second maximum number. Here is an attempt I gave in the interview:
#define MIN -1
int main()
{
int max=MIN,second_max=MIN;
int arr[6]={0,1,2,3,4,5};
for(int i=0;i<5;i++){
cout<<"::"<<arr[i];
}
for(int i=0;i<5;i++){
if(arr[i]>max){
second_max=max;
max=arr[i];
}
}
cout<<endl<<"Second Max:"<<second_max;
int i;
cin>>i;
return 0;
}
The interviewer, however, came up with the test case int arr[6]={5,4,3,2,1,0};, which prevents it from going to the if condition the second time.
I said to the interviewer that the only way would be to parse the array two times (two for loops). Does anybody have a better solution?
Your initialization of max and second_max to -1 is flawed. What if the array has values like {-2,-3,-4}?
What you can do instead is to take the first 2 elements of the array (assuming the array has at least 2 elements), compare them, assign the smaller one to second_max and the larger one to max:
if(arr[0] > arr[1]) {
second_max = arr[1];
max = arr[0];
} else {
second_max = arr[0];
max = arr[1];
}
Then start comparing from the 3rd element and update max and/or second_max as needed:
for(int i = 2; i < arr_len; i++){
// use >= n not just > as max and second_max can hav same value. Ex:{1,2,3,3}
if(arr[i] >= max){
second_max=max;
max=arr[i];
}
else if(arr[i] > second_max){
second_max=arr[i];
}
}
The easiest solution would be to use std::nth_element.
You need a second test:
for(int i=0;i<5;i++){
if(arr[i]>max){
second_max=max;
max=arr[i];
}
else if (arr[i] > second_max && arr[i] != max){
second_max = arr[i];
}
}
Your original code is okay, you just have to initialize the max and second_max variables. Use the first two elements in the array.
Here you are:
std::pair<int, int> GetTwoBiggestNumbers(const std::vector<int>& array)
{
std::pair<int, int> biggest;
biggest.first = std::max(array[0], array[1]); // Biggest of the first two.
biggest.second = std::min(array[0], array[1]); // Smallest of the first two.
// Continue with the third.
for(std::vector<int>::const_iterator it = array.begin() + 2;
it != array.end();
++it)
{
if(*it > biggest.first)
{
biggest.second = biggest.first;
biggest.first = *it;
}
else if(*it > biggest.second)
{
biggest.second = *it;
}
}
return biggest;
}
Quickselect is the way to go with this one. Pseudo code is available at that link so I shall just explain the overall algorithm:
QuickSelect for kth largest number:
Select a pivot element
Split array around pivot
If (k < new pivot index)
perform quickselect on left hand sub array
else if (k > new pivot index)
perform quickselect on right hand sub array (make sure to offset k by size of lefthand array + 1)
else
return pivot
This is quite obviously based on the good old quicksort algorithm.
Following this algorithm through, always selecting element zero as the pivot every time:
select 4th largest number:
1) array = {1, 3, 2, 7, 11, 0, -4}
partition with 1 as pivot
{0, -4, _1_, 3, 2, 7, 11}
4 > 2 (new pivot index) so...
2) Select 1st (4 - 3) largest number from right sub array
array = {3, 2, 7, 11}
partition with 3 as pivot
{2, _3_, 7, 11}
1 < 2 (new pivot index) so...
3) select 1st largest number from left sub array
array = {2}
4) Done, 4th largest number is 2
This will leave your array in an undefined order afterwards, it's up to you if that's a problem.
Step 1. Decide on first two numbers.
Step 2. Loop through remaining numbers.
Step 3. Maintain latest maximum and second maximum.
Step 4. When updating second maximum, be aware that you are not making maximum and second maximum equal.
Tested for sorted input (ascending and descending), random input, input having duplicates, works fine.
#include <iostream>
#define MAX 50
int GetSecondMaximum(int* data, unsigned int size)
{
int max, secmax;
// Decide on first two numbers
if (data[0] > data[1])
{
max = data[0];
secmax = data[1];
}
else
{
secmax = data[0];
max = data[1];
}
// Loop through remaining numbers
for (unsigned int i = 2; i < size; ++i)
{
if (data[i] > max)
{
secmax = max;
max = data[i];
}
else if (data[i] > secmax && data[i] != max/*removes duplicate problem*/)
secmax = data[i];
}
return secmax;
}
int main()
{
int data[MAX];
// Fill with random integers
for (unsigned int i = 0; i < MAX; ++i)
{
data[i] = rand() % MAX;
std::cout << "[" << data[i] << "] "; // Display input
}
std::cout << std::endl << std::endl;
// Find second maximum
int nSecondMax = GetSecondMaximum(data, MAX);
// Display output
std::cout << "Second Maximum = " << nSecondMax << std::endl;
// Wait for user input
std::cin.get();
return 0;
}
Other way to solve this problem, is to use comparisons among the elements. Like for example,
a[10] = {1,2,3,4,5,6,7,8,9,10}
Compare 1,2 and say max = 2 and second max = 1
Now compare 3 and 4 and compare the greatest of them with max.
if element > max
second max = max
element = max
else if element > second max
second max = element
The advantage with this is, you are eliminating two numbers in just two comparisons.
Let me know, if you have any problem understanding this.
Check this solution.
max1 = a[0];
max2 = a[1];
for (i = 1; i < n; i++)
{
if (max1 < a[i])
{
max2 = max1;
max1 = a[i];
}
if (max2 == max1) max2 = a[i + 1];
if (max2 == a[n])
{
printf("All numbers are the same no second max.\n");
return 0;
}
if (max2 < a[i] && max1 != a[i]) max2 = a[i];
}
Here is something which may work ,
public static int secondLargest(int[] a){
int max=0;
int secondMax=0;
for(int i=0;i<a.length;i++){
if(a[i]<max){
if(a[i]>secondMax){
secondMax=a[i];
}
continue;
}
if(a[i]>max){
secondMax=max;
max=a[i];
}
}
return secondMax;
}
The upper bound should have be n+log2⁡n−2, but it bigger than O(n) in case of random selection algorithm, but in worst case it much smaller. The solution might be
build a tree like to find the MAX element with n - 1 comparisons
max(N)
/ \
max(N/2) max(N/2)
remove the MAX and find the MAX again log2n - 1 comparison
PS. It uses additional memory, but it faster than random selection algorithm in worst case.
Can't we just sort this in decreasing order and take the 2nd element from the sorted array?
How about the following below.
make_heap is O(n) so this is efficient and this is 1-pass
We find the second max by taking advantage that it must be one of the heap children of the parent, which had the maximum.
#include <algorithm>
#include <iostream>
int main()
{
int arr[6]={0,1,2,3,4,5};
std::make_heap(arr, arr+6);
std::cout << "First Max: " << arr[0] << '\n';
std::cout << "Second Max: " << std::max(arr[1], arr[2]) << '\n';
return 0;
}
int max,secondMax;
max=secondMax=array[0];
for(int i=0;i<array.length;i++)
{ if(array[i]>max) { max=array[i]; }
if(array[i]>secondMax && array[i]<max) {
secondMax=array[i]; }
}
#include <iostream>
using namespace std;
int main() {
int max = 0;
int sec_Max = 0;
int array[] = {81,70,6,78,54,77,7,78};
int loopcount = sizeof(array)/sizeof(int);
for(int i = 0 ; i < loopcount ; ++i)
{
if(array[i]>max)
{
sec_Max = max;
max = array[i];
}
if(array[i] > sec_Max && array[i] < max)
{
sec_Max = array[i];
}
}
cout<<"Max:" << max << " Second Max: "<<sec_Max<<endl;
return 0;
}
// Set the first two different numbers as the maximum and second maximum numbers
int max = array[0];
int i = 1;
//n is the amount of numbers
while (array[i] == max && i < n) i++;
int sec_max = array[i];
if( max < sec_max ) {
tmp = sec_max;
sec_max = max;
max = tmp;
}
//find the second maximum number
for( ; i < n; ++i ) {
if( array[i] > max ) {
sec_max = max;
max = array[i];
} else if( array[i] > sec_max && array[i] != max ) {
sec_max = array[i];
}
}
printf("The second maximum number is %d\n", sec_max);