Flip cards to get maximum sum - c++

Given N cards where if ith card has number x on its front side then it will have -x on back side and a single operation that can be done only once that is to flip any number of cards in consecutive order only once.
Now we need to flip cards in such a way that sum of number of upper face of cards is maximum.
Example : If N=5 and cards[] be {-2,3,-1,-4,-2} then here answer is 8 as we can flip last 3 cards to get configuration {-2,3,1,4,2} which sum to 8.
My Approach :
Go for each possible way for each ith position as start position and find the maximum.But is their any better solution to this problem?
My Code : Am not able to find problem till yet
#include<bits/stdc++.h>
using namespace std;
int solve(std::vector<int> const & numbers)
{
int min_so_far = numbers[0], min_ending_here = numbers[0];
size_t begin = 0;
size_t begin_temp = 0;
size_t end = 0;
for(size_t i = 1; i < numbers.size(); i++)
{
if(min_ending_here > 0)
{
min_ending_here = numbers[i];
begin_temp = i;
}
else
{
min_ending_here += numbers[i];
}
if(min_ending_here <= min_so_far )
{
min_so_far = min_ending_here;
begin = begin_temp;
end = i;
}
}
int sum=0;
for(int i=0;i<begin;i++){
sum+=numbers[i];
}
for(int i=begin;i<=end;i++){
sum-=numbers[i];
}
for(int i=end+1;i<numbers.size();i++){
sum+=numbers[i];
}
return sum;
}
int main(){
int n;
cin>>n;
vector<int> arr;
for(int i=0;i<n;i++){
int x;
cin>>x;
arr.push_back(x);
}
cout<<solve(arr)<<"\n";
}

The only thing you need to find is the minimum sum that you can form with consecutive numbers, and then flip those. In your example, the last three numbers add up to -7, and there is no other set of consecutive number which have a lower sum, so flipping them does the trick. If the minimum sum is non negative, then you don't need to flip them.
Now, what I described above is a well known algorithm, and it is called Kadane's algorithm, which can be solve in O(n), notice that the Wikipedia link shows how to do it for the maximum, but you can easily modify it to find the minimum.

I used Kadane's algorithm approach in this and the Minimum Subarray Sum function returns the minimum sum in O(n) and since we already had the sum of all elements of the array so we will add (-2) time of min_sum as it was deducted once.
#include<bits/stdc++.h>
using namespace std;
int minsubarraysum(int a[], int n) {
int min_sum = INT_MAX;
int curr_sum = 0;
for (int i = 0 ; i < n; i++) {
curr_sum = curr_sum + a[i];
if (curr_sum < min_sum)
min_sum = curr_sum;
if (curr_sum > 0)
curr_sum = 0;
}
return min_sum;
}
int main() {
int n;
cin >> n;
int a[n];
int sum = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
sum += a[i];
}
int min_sum = minsubarraysum(a, n);
int ans = sum + (min_sum * (-2));
cout << ans;
}

Related

Sum of the two lowest positive numbers in a vector

I made a function sumOfTwoSmallestNumbers() that takes an integer vector (containing only positive values) and it returns the sum of the two lowest positive numbers stored in that vector. Unfortunately, my function fails for a few test cases (I do not have access to the inputs of those test cases). Please help me find the error in my code.
NOTE: Vector always consists of a minimum of 4 positive values
#include <iostream>
#include <vector>
using namespace std;
long sumOfTwoSmallestNumbers (vector<int> numbers)
{
long int sum = 0;
long int min1 = numbers[0];
int position;
for (unsigned long int i = 0; i < numbers.size(); i++){
if (numbers[i] < min1){
min1 = numbers[i];
position = i;
}
}
numbers.erase(numbers.begin() + position - 1);
long int min2 = numbers[0];
for (unsigned long int i = 0; i < numbers.size(); i++){
if (numbers[i] < min2){
min2 = numbers[i];
}
}
sum = min1 + min2;
return sum;
}
Logic:
I have tried to first find the smallest value and store it in a variable and then remove that value from the vector. After that, I again searched for the smallest value in the vector and stored it in a variable. In end, I have added the two values and returned the sum.
Your code has a couple of issues:
If the smallest number in the vector is the first, position will be uninitialized and cause UB (Undefined Behavior).
If you'll initiazlie position to 0 as required, then again if the smallest number in the vector is the first, this line numbers.erase(numbers.begin() + position - 1) will attempt to use an iterator to before numbers.begin(). This is invalid.
My solution below only keeps track of smallest and secondSmallest without having to modify the vector at all (and thus I can pass it by const&). It also requires only one traverse of the vector (and the complexity is O(n)).
#include <iostream>
#include <vector>
#include <assert.h>
long sumOfTwoSmallestNumbers(std::vector<int> const & numbers)
{
assert(numbers.size() >= 4); // The OP specified that in the question.
int smallest = (numbers[0] < numbers[1]) ? numbers[0] : numbers[1];
int secondSmallest = (numbers[0] < numbers[1]) ? numbers[1] : numbers[0];
for (size_t i = 2; i < numbers.size(); ++i)
{
if (numbers[i] < smallest)
{
// Need to update both:
secondSmallest = smallest;
smallest = numbers[i];
}
else if (numbers[i] < secondSmallest)
{
// Need to update only second:
secondSmallest = numbers[i];
}
}
return (smallest + secondSmallest);
}
int main()
{
std::vector<int> v = { 1,4,7,2 };
auto s = sumOfTwoSmallestNumbers(v);
std::cout << "sumOfTwoSmallestNumbers: " << s << std::endl;
return 0;
}
Output:
sumOfTwoSmallestNumbers: 3
A side note: it's better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
What do you think of this:
// Simple function that will swap smallest with next_smallest
// if smallest > next_smallest. Returns true if a swap happened
bool TwoItemSort(int& smallest, int& next_smallest)
{
if (next_smallest < smallest)
{
int tmp = smallest;
smallest = next_smallest;
next_smallest = tmp;
return true;
}
return false;
}
long sumOfTwoSmallestNumbers(const vector<int>& numbers)
{
if (numbers.size() < 2)
{
return 0;
}
int smallest = numbers[0];
int nextsmallest = numbers[1];
TwoItemSort(smallest, nextsmallest);
for (size_t i = 2; i < numbers.size(); i++)
{
int value = numbers[i];
if (TwoItemSort(nextsmallest, value))
{
TwoItemSort(smallest, nextsmallest);
}
}
return smallest + nextsmallest;
}
um, this is a two-liner...
std::sort(vec.begin(),vec.end());
auto sum = vec.at(0) + vec.at(1);
Hope this helps
Caveat: it does not skip negative numbers, but that has been left out as a learning exercise for the OP.
#include <bits/stdc++.h>
using namespace std;
int sumOfSmallestPositive(vector<int> arr);
int main()
{
vector<int> arr{-8,-24,14,-56,-1,5,87,12,-10,11};
cout<<sumOfSmallestPositive(arr);
return 0;
}
int sumOfSmallestPositive(vector<int> arr)
{
sort(arr.begin(),arr.end());
pair<int,int> p;
for(int i=0;i<arr.size();i++)
{
if(arr[i]>0)
{
p.first=arr[i];
p.second=0;
if(i+1<=arr.size()-1)
p.second=arr[i+1];
break;
}
}
return p.first +p.second; //return 5+11=16
}

changing last maximum with first minimum using arrays

I am trying to implement a c++ program that when a given a sequence, it tries to change the first minimum with the last maximum. My code is tested on my university's e-judge. It passes 32 test cases, but gets stuck at the 32 one. Can you spot what might be wrong, about the better Int, it's just for a bigger number. the program statement is that input contains a natural n – the quantity of numbers in a sequence, then n numbers – elements of a sequence.
Output should be the changed sequence of numbers.
#include <iostream>
//#include <cmath>
#include <climits>
#define SIZE 100000
using namespace std;
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
long long int a[SIZE], min, max;
int n, min_i, max_i; min = 0x7fffffffffffffff; max = -1;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
if (a[i] < min) { min = a[i]; min_i = i; }
if (a[i] >= max) { max = a[i]; max_i = i; }
}
a[max_i] = min; a[min_i] = max;
for (int i = 0; i < n; i++) {
cout << a[i] << " ";
}
return 0;
}
By the way, for the largest maximum number, I tried, int_max, uint_max, better INT, all the same when it comes to failing the 32nd test case.
Is it guaranteed that the input sequence (n in your code) is with no more than SIZE (100000 in the code) elements?
Are you allowed to use dynamic memory allocation instead?
Is it guaranteed that n will be at least 1?
If it is 0 both min_i and max_i would have indeterminate state which could crash your program when you use them as indexes: a[max_i] = min; a[min_i] = max;.
If the above two assumptions are valid, I would do what #paddy and #Frodyne already suggested and initialize all variables with valid data before going into the main loop:
size_t min_i = 0;
size_t max_i = 0;
cin >> a[0];
min = a[0];
max = a[0];
for (size_t i = 1; i < n; i++) { ... }

Counting not equal strings in array in C++

I want to count all the different string elements in an array.
So my input would be:
5 Lemon Orange Lemon Mango Lemon
And the output should be this:
3
The problem with my code is, that my code counts all the elements, and not just the different and I can't figure out why.
Here is my code:
#include <iostream>
using namespace std;
int main()
{
int N;
cin >> N;
string Tname;
string data[N];
int counter = 0;
for(int i = 0; i<N; i++)
{
cin >> Tname;
data[i] = Tname;
}
for(int l = 0; l<N; l++)
{
int k = 0;
while(k<N && (data[l] != data[k]))
{
k++;
}
if(k<N)
{
counter += 1;
}
}
cout << counter << endl;
return 0;
}
The problem is algorithmic: every item is equal to itself, which will end your k loop prematurely. In addition, you only increment when the item is repeated.
I propose you to change the loops, so not to compare every items with every other items, but only items, to items previously processed:
for(int l = 0; l<N; l++)
{
int k = 0;
while(k<l && data[l] != data[k]) // only previous items
{
k++;
}
if(k==l) // if no identical, we can add this one
{
cout<<l<<" "<<data[l]<<endl;
counter += 1;
}
}
Not related: variable length arrays are not legal C++ even if some mainstream compilers accept it. I'd suggest to use a vector to emulate this feature: vector<string> data(N);
Online demo
if i understand well your problem , you want the value that has the max appearances in the array, some modifications are needed to achieve this :
#include <iostream>
using namespace std;
int main()
{
int N;
cin >> N;
string Tname;
string data[N];
int counter = 0;
for(int i = 0; i<N; i++)
{
cin >> Tname;
data[i] = Tname;
}
int tempCounter; // a temporary counter for each item of the array .
for(int l = 0; l < N; l++)
{
tempCounter = 0;
int k = 0;
while(k<N)
{
if(data[l] == data[k])
tempCounter++;
k++;
}
if(tempCounter > counter) // if the new counter is higher than the counter
counter = tempCounter;
}
cout << counter << endl;
return 0;
}
the last if should be if(k+1==N)
because you all the time stop the while before the k reach N
and k must start from l
Your logic is, you add 1 to the counter if it is not in the list's remaining part
But the code check the full list so you never count thw world whitch in the list twice.

How to generate all n-digit number in the n-digit-array way?

I know how to generate all n-digit number in the traditional number way,
for(long long number = pow(10, n-1); number < pow(10, n); number++) {
cout << number << endl;
}
for example,
for n = 5, it will generate 10000 to 99999;
However, since I will have to evaluate each number's digits, it is much convenient to construct the numbers in a digit array format in the first place.
for example, following code generate all 5-digit number in an array way:
for(int i = 1; i < 9; i++)
for(int j = 0; j < 9; j++)
for(int k = 0; k < 9; k++)
for(int l = 0; l < 9; l++)
for(int m = 0; m < 9; m++) {
//executed 9 * 10^4 = 90000 times
//construct my array instance with i, j, k, l, m
cout << i << j << k << l << m << endl;
}
Now the problem is: n is unknown. (for example, it could be 2, 3, 4, 5, 6..., 10)
Then how can I generate n-digit-array based on a number n?
For example, I want a piece of code like follows (any better ways than this one is highly appreciated):
for(int x = 0; x < n; x++) {
//each x is a layer of the loop ?!
.....
}
There is no reason to limit ourselves to the range 0 - 9 for each digit of the number.
For each numerical place, we'll represent a range:
std::pair<int,int> range;
Each loop in your example is iterating from the beginning of the range to the end of the range.
All the loops together are really just a series of ranges; each nested loop being responsible for the next digit of your generated number.
We can represent that, in the following way:
std::vector<std::pair<int, int>> ranges;
If you think about how nested for loops work, you can emulate the same functionality over the vector using two pointers. I've done that and wrapped the functionality into a class:
//header
class Range_Combinator {
public:
Range_Combinator(std::vector<std::pair<int, int>> const &ranges_in);
std::vector<int> Next();
std::vector<int> Current();
bool Done();
private:
bool Adjust();
void Reset_From_Current_Back(int from);
std::vector<std::pair<int, int>> ranges;
int current;
int last;
bool all_exausted;
std::vector<int> current_vals;
};
//source
Range_Combinator::Range_Combinator(
std::vector<std::pair<int, int>> const &ranges_in) {
ranges = ranges_in;
last = ranges.size() - 1;
current = last;
all_exausted = false;
for (auto it : ranges) {
current_vals.push_back(it.first);
}
}
std::vector<int> Range_Combinator::Next() {
all_exausted = Adjust();
return current_vals;
}
std::vector<int> Range_Combinator::Current() { return current_vals; }
bool Range_Combinator::Done() { return all_exausted; }
bool Range_Combinator::Adjust() {
if (current_vals[current] < ranges[current].second) {
current_vals[current]++;
} else {
while (current_vals[current] == ranges[current].second) {
current--;
}
if (current < 0) {
return true;
}
Reset_From_Current_Back(current + 1);
current_vals[current]++;
current = last;
}
return false;
}
void Range_Combinator::Reset_From_Current_Back(int from) {
for (int i = from; i <= last; ++i) {
current_vals[i] = ranges[i].first;
}
}
This is how you would use it:
//create range combinator
std::vector<std::pair<int,int>> ranges{{1,2},{3,4}};
Range_Combinator r(ranges);
//print each number
auto number = r.Current();
while (!r.Done()){
for (auto it: number) std::cout << it; std::cout << '\n';
number = r.Next();
}
//prints: 13
// 14
// 23
// 24
I don't know why you need that but you can try this:
size_t n = ; //whatever value
unsigned char* x = new unsigned char[n]();
x[0] = 1; //make it n-digit 10000...000
do
{
//process digits here
++x[n - 1];
for (size_t i = n; i > 1; --i)
{
if (x[i - 1] == 10)
{
x[i - 1] = 0;
++x[i - 2];
}
}
} while (x[0] < 10);
delete [] x;
You can even process not decimal numbers, just replace hard-coded 10 into appropriate number.
I suppose I could just write out the whole thing for you, but that would be no fun. Instead, I'll just outline the basic approach, and you can finish the answer yourself by filling in the blanks.
Consider an n-digit long number being represented this way:
struct digit {
struct digit *next;
int n; /* Digit 0-9 */
};
A single number represented, in this manner, can be printed out this way:
void print_digit(struct digit *p)
{
while (p)
{
std::cout << p->n;
p=p->next;
}
std::cout << std::endl;
}
Now, let's create a recursive loop, that iterates over all possible n-digit numbers:
void iterate(int ndigits)
{
for (int i=0; i<10; ++i)
{
if (ndigits > 1)
{
iterate(ndigits-1);
}
else
{ // This is the last digit
// Here be dragons
}
}
}
After a bit of thinking, you can see that if, for example, you call iterate(4), then when the "hear be dragons" part gets executed, this will be inside a four-deep nested iteration stack. There will be four level-deep for loops, nested within each other. And, with iterate(6), there will be six of them, and so on.
Now, consider the fact that the struct digit-based representation of n-digit numbers is also a stack, of sorts.
Therefore, the homework assignment here would be to use this recursive iteration to dynamically construct this linked list, on the stack, with the "here be dragons" part simply invoking print_digit() in order to print each number.
Hint: iterate() will need to have a few more parameters, that it will use appropriately, with a certain preset value for them, on the initial call to iterate().
A simple way without thinking of efficiency:
#include <cstdio>
int main(void) {
int n = 3; // the number of digits
long long start = 1;
int *array = new int[n];
for (int i = 1; i < n; i++) start *= 10;
for(long long x = start; x < start * 10; x++) { // not all 10-digit number will fit in 32-bit integer
// get each digits in decimal, lowest digit in array[0]
for (int i = 0, shift = 1; i < n; i++, shift *= 10) array[i] = (int)((x / shift) % 10);
// do some work with it (print it here)
for (int i = n - 1; i >= 0; i--) printf("%d", array[i]);
putchar('\n');
}
delete[] array;
return 0;
}

lexicographically smallest string after rotation

I am trying to solve this problem in spoj
I need to find the number of rotations of a given string that will make it lexicographically smallest among all the rotations.
For example:
Original: ama
First rotation: maa
Second rotation: aam This is the lexicographically smallest rotation so the answer is 2.
Here's my code:
string s,tmp;
char ss[100002];
scanf("%s",ss);
s=ss;
tmp=s;
int i,len=s.size(),ans=0,t=0;
for(i=0;i<len;i++)
{
string x=s.substr(i,len-i)+s.substr(0,i);
if(x<tmp)
{
tmp=x;
t=ans;
}
ans++;
}
cout<<t<<endl;
I am getting "Time Limit Exceeded" for this solution. I don't understand what optimizations can be made. How can I increase the speed of my solution?
You can use a modified suffix array. I mean modified because you must not stop on word end.
Here is the code for a similar problem I solved (SA is the suffix array):
//719
//Glass Beads
//Misc;String Matching;Suffix Array;Circular
#include <iostream>
#include <iomanip>
#include <cstring>
#include <string>
#include <cmath>
#define MAX 10050
using namespace std;
int RA[MAX], tempRA[MAX];
int SA[MAX], tempSA[MAX];
int C[MAX];
void suffix_sort(int n, int k) {
memset(C, 0, sizeof C);
for (int i = 0; i < n; i++)
C[RA[(i + k)%n]]++;
int sum = 0;
for (int i = 0; i < max(256, n); i++) {
int t = C[i];
C[i] = sum;
sum += t;
}
for (int i = 0; i < n; i++)
tempSA[C[RA[(SA[i] + k)%n]]++] = SA[i];
memcpy(SA, tempSA, n*sizeof(int));
}
void suffix_array(string &s) {
int n = s.size();
for (int i = 0; i < n; i++)
RA[i] = s[i];
for (int i = 0; i < n; i++)
SA[i] = i;
for (int k = 1; k < n; k *= 2) {
suffix_sort(n, k);
suffix_sort(n, 0);
int r = tempRA[SA[0]] = 0;
for (int i = 1; i < n; i++) {
int s1 = SA[i], s2 = SA[i-1];
bool equal = true;
equal &= RA[s1] == RA[s2];
equal &= RA[(s1+k)%n] == RA[(s2+k)%n];
tempRA[SA[i]] = equal ? r : ++r;
}
memcpy(RA, tempRA, n*sizeof(int));
}
}
int main() {
int tt; cin >> tt;
while(tt--) {
string s; cin >> s;
suffix_array(s);
cout << SA[0]+1 << endl;
}
}
I took this implementation mostly from this book. There is an easier to write O(n log²n) version, but may not be efficient enough for your case (n=10^5). This version is O(n log n), and it's not the most efficient algorithm. The wikipedia article lists some O(n) algorithms, but I find most of them too complex to write during a programming contest. This O(n log n) is usually enough for most problems.
You can find some slides explaining suffix array concept (from the author of the book I mentioned) here.
I know this comes very late but I stumbled across this from google on my search for an even faster variant of this algorithm. Turns out a good implementation is found at github: https://gist.github.com/MaskRay/8803371
It uses the lyndon factorization. That means it repeatly splits the string into lexicographically decreasing lyndon words. Lyndon word are strings that are (one of) the minimal rotations of themselves. Doing this in a circular way yields the lms of the string as the last found lyndon word.
int lyndon_word(const char *a, int n)
{
int i = 0, j = 1, k;
while (j < n) {
// Invariant: i < j and indices in [0,j) \ i cannot be the first optimum
for (k = 0; k < n && a[(i+k)%n] == a[(j+k)%n]; k++);
if (a[(i+k)%n] <= a[(j+k)%n]) {
// if k < n
// foreach p in [j,j+k], s_p > s_{p-(j-i)}
// => [j,j+k] are all suboptimal
// => indices in [0,j+k+1) \ i are suboptimal
// else
// None of [j,j+k] is the first optimum
j += k+1;
} else {
// foreach p in [i,i+k], s_p > s_{p+(j-i)}
// => [i,i+k] are all suboptimal
// => [0,j) and [0,i+k+1) are suboptimal
// if i+k+1 < j
// j < j+1 and indices in [0,j+1) \ j are suboptimal
// else
// i+k+1 < i+k+2 and indices in [0,i+k+2) \ (i+k+1) are suboptimal
i += k+1;
if (i < j)
i = j++;
else
j = i+1;
}
}
// j >= n => [0,n) \ i cannot be the first optimum
return i;
}