How to find a subarray with minimum k length and maximum sum? - c++

The subarray contains both positive and negative numbers. You have to find a maximum sum subarray such that the length of the sub-array is greater than or equal to k.
Here is my code in c++ using Kadane's algorithm.
#include <iostream>
using namespace std;
int main(){
int n,k;
cin >> n >> k;
int array[n];
int sum = 0;
int maxsum = 0;
int beststarts[n];
for(int i = 0;i < n; i++){
cin >> array[i];
}
for(int i = 0;i < k-1;i ++){
sum = sum+array[i];
beststarts[i] = 0;
}
for(int i = k-1;i < n; i++){ //best end search with min length;
sum = sum+array[i];
int testsum = sum;
if(i > 0){
beststarts[i] = beststarts[i-1];
}
for(int j = beststarts[i] ;i-j > k-1;j ++){
testsum = testsum - array[j];
if(testsum > sum){
beststarts[i] = j+1;
sum = testsum;
}
}
if(sum > maxsum){
maxsum = sum;
}
}
cout << maxsum;
return 0;
}
My code is working fine but it is very slow, and i cant think of any ways to improve my code. I have also read this question Find longest subarray whose sum divisible by K but that is not what i want, the length can be greater than k also.

Solution based on this answer
Live demo
#include <algorithm>
#include <iterator>
#include <iostream>
#include <numeric>
#include <ostream>
#include <utility>
#include <vector>
// __________________________________________________
template<typename RandomAccessIterator> typename std::iterator_traits<RandomAccessIterator>::value_type
max_subarr_k(RandomAccessIterator first,RandomAccessIterator last,int k)
{
using namespace std;
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
if(distance(first,last) < k)
return value_type(0);
RandomAccessIterator tail=first;
first+=k;
value_type window=accumulate(tail,first,value_type(0));
value_type max_sum=window, current_sum=window;
while(first!=last)
{
window += (*first)-(*tail) ;
current_sum = max( current_sum+(*first), window );
max_sum = max(max_sum,current_sum);
++first;
++tail;
}
return max_sum;
}
// __________________________________________________
template<typename E,int N>
E *end(E (&arr)[N])
{
return arr+N;
}
int main()
{
using namespace std;
int arr[]={1,2,4,-5,-4,-3,2,1,5,6,-20,1,1,1,1,1};
cout << max_subarr_k(arr,end(arr),4) << endl;
cout << max_subarr_k(arr,end(arr),5) << endl;
}
Output is:
14
11

int w(0);
for (int i=0; i < k; i++) w += a[i];
int run_sum(w), max_sum(w);
for (int i=k; i < n; i++) {
w = a[i] + max(w, w-a[i-k]); // window will such that it will include run_sum
run_sum = max(run_sum + a[i], w);
max_sum = max(run_sum, max_sum);
}
return max_sum;

Related

Debugging a Sums of Digit Factorials

I would to solve this problem illustrated in this image using C++
Define f(n) as the sum of the factorials of the digits of n. For example, f(342) = 3! + 4! + 2! = 32.
Define sf(n) as the sum of the digits of f(n). So sf(342) = 3 + 2 = 5.
Define g(i) to be the smallest positive integer n such that sf(n) = i. Though sf(342) is 5, sf(25) is also 5, and it can be verified that g(5) is 25.
Define sg(i) as the sum of the digits of g(i). So sg(5) = 2 + 5 = 7.
Further, it can be verified that g(20) is 267 and ∑ sg(i) for 1 ≤ i ≤ 20 is 156.
What is ∑ sg(i) for 1 ≤ i ≤ 150?
Image:
Here is my approach. My code takes long time running, and it works
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int factorial(int n);
std::vector<int> int_to_vector(int n);
int sum_vector(std::vector<int> v);
int get_smallest_number(std::vector<int> v, int sum, int n);
int sum_sg(int n )
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int q;
int m,n;
int g;
int sum = 0;
std::vector<int> vec;
cin>>q;
if( 1<=q && q<=100000){
std::vector<int> s;
int fact = 0;
int sg = 0;
for ( int i = 0; i < q; i++){
cin>>n>>m;
fact = factorial(n);
s = int_to_vector(fact);
sum = sum_vector(s);
g = get_smallest_number(s, sum, n);
s = int_to_vector(g);
sum = sum_vector(s);
}
}
return 0;
}
int factorial(int n){
if (n==0) return 1;
return factorial(n-1)*n;
}
std::vector<int> int_to_vector(int n){
std::vector<int> numbers;
while(n>0)
{
numbers.push_back(n%10);
n/=10;
}
return numbers;
}
int sum_vector(std::vector<int> v){
int sum=0;
for(int i = 0; i < v.size(); i++){
sum+=v.at(i);
}
return sum;
}
int get_smallest_number(std::vector<int> v, int sum, int n){
int i = 0;
int factoriel = 1;
std::vector<int> vect;
int sum2 = 0;
while( i < n){
factoriel = factorial(i);
vect = int_to_vector(factoriel);
sum2 = sum_vector(vect);
if( sum2 == sum) return i;
i++ ;
}
return n;
}
I think on recursive solutions, but it seems somehow more complex to implement. Are there any solutions using modern C++ and STL?
Here is below a bad solution with less complexity, please any suggestion to have good and fast code rather than this below,
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
std::vector<int> factorial {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
std::vector<int> int_to_vector(int n);
int sum_vector(std::vector<int> v);
int find_g(int i);
int calculat_sum_fact(std::vector<int> v);
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int m,n,q;
std::vector<int> vec;
std::vector<int> s;
std::vector<int> numbers;
cin>>q;
for (int i = 0; i < q; i++){
cin>>n>>m;
numbers.push_back(n);
// cout<< numbers.at(i);
}
for(int k = 0; k < numbers.size(); k++){
int sum = 0;
for (int i = 0; i < numbers.at(k)+1; i++){
s = int_to_vector(find_g(i));
sum += sum_vector(s);
}
cout << sum << "\n";
}
return 0;
}
std::vector<int> int_to_vector(int n){
std::vector<int> numbers;
while(n>0)
{
numbers.push_back(n%10);
n/=10;
}
return numbers;
}
int sum_vector(std::vector<int> v){
int sum=0;
for(int i = 0; i < v.size(); i++){
sum+=v.at(i);
}
return sum;
}
int find_g(int i){
std::vector<int> s ;
int sum = 0;
int j = 0;
//cout<<"sf 1= " << j << endl;
while(true){
s = int_to_vector(j);
sum = calculat_sum_fact(s);
s= int_to_vector(sum);
sum = sum_vector(s);
//cout<<"sf 2= " << j << endl;
if (sum == i) {
//cout<<"sf = " << j << endl;
return j;
//break;
}
//cout<<"sf = " << j << endl;
j++;
}
}
int calculat_sum_fact(std::vector<int> v){
int sum = 0;
for(int i = 0; i < v.size(); i++ ){
sum += factorial.at(v.at(i));
}
return sum;
}

Time limit exceeded on codeforces

I've been stuck on this problem for a pretty Long while. I always get "Time limit exceeded" when I submit the code.
My solution is to input the items of the array then determine the largest number in the array and diplay it along with the elements following it and so on.
How can I make my algorithm more efficient?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int T, n;
cin >> T;
while (T--) {
//inputting p[n]
scanf_s("%d", &n);
int* p = new int[n];
for (int i = 0; i < n; i++) {
scanf_s("%d", &p[i]);
}
while (n != 0) {
//*itr = largest element in the array
auto itr = find(p, p + n, *max_element(p, p + n));
int index = distance(p, itr);
for (int i = index; i < n; i++) {
printf("%d\n", p[i]);
}
//deleting element by decreasing n:
n = index;
}
delete[] p;
}
return 0;
}
You solution is O(n^2), too slow.
A O(n) solution is obtained by iteratively calculating the position of the max element until a given index i.
#include <iostream>
#include <vector>
#include <algorithm>
//using namespace std;
int main() {
int T;
std::cin >> T;
while (T--) {
//inputting p[n]
int n;
std::cin >> n;
std::vector<int> p(n);
for (int i = 0; i < n; i++) {
std::cin >> p[i];
}
std::vector<int> max_before(n);
max_before[0] = 0;
for (int i = 1; i < n; ++i) {
if (p[i] > p[max_before[i-1]]) {
max_before[i] = i;
} else {
max_before[i] = max_before[i-1];
}
}
while (n != 0) {
int index = max_before[n-1];
for (int i = index; i < n; i++) {
std::cout << p[i] << " ";
}
//deleting element by decreasing n:
n = index;
}
std::cout << '\n';
}
return 0;
}

Code optimization for insertion sort advance analysis

#include <string>
#include <numeric>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
int main() {
int n, n1, n2, index, max = 0;
long cnt = 0;
vector <int> arr;
vector <int> arr1;
cin >> n;
for (int i = 0; i < n; i++) {
cnt = 0, max = 0;
cin >> n1;
arr.clear();
arr1.clear();
for (int j = 0; j < n1; j++) {
cin >> n2;
arr.push_back(n2);
if (n2 > max) max = n2;
}
for (int j = 0; j <= max; j++) {
arr1.push_back(j);
arr1[j] = 0;
}
for (int j = n1 - 1; j >= 0; j--) {
index = arr[j] - 1;
while (index > 0) {
cnt += arr1[index];
index -= (index & -index);
}
index = arr[j];
while (index <= max) {
arr1[index] += 1;
index += (index & -index);
}
}
cout << cnt << endl;
}
}
I've been trying to solve the insertion sort advanced analysis but my code times out. Is there a way I can optimize the code more? The objective of the problem is to find the total number of times the array has to shift.
I've tried to use BIT for the first time.
n is for the number of tests.
n1 is for the amount of numbers that will be inputted.
arr is a vector to save the inputs.
arr1 is a vector to save the amount for each number.
Sorry for the bad english.

Non-repeating random numbers in vector C++

I'm trying to store random numbers in vector, but I want each number to be unique. Can I do that with for loop without using unique() or random_shuffle() ?
#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
int main()
{
srand(time(NULL));
vector<int> v;
for (unsigned int i = 0; i < 30; i++) {
v.push_back(rand() % 30);
}
for (unsigned int j = 0; j < 30; j++) {
cout << v[j] << endl;
}
return 0;
}
The classic Fisher–Yates shuffle can also be used to generate a shuffled vector directly, in one pass
vector<unsigned> v;
for (unsigned i = 0; i < 30; ++i)
{
unsigned j = rand() % (i + 1);
if (j < i)
{
v.push_back(v[j]);
v[j] = i;
}
else
v.push_back(i);
}
You should probably generate vector and just shuffle it:
#include <iostream>
#include <ctime>
#include <utility>
int main()
{
std::srand(static_cast<unsigned int>(std::time(NULL)));
size_t const n = 30;
std::vector<int> v(n);
//make vector
for (size_t i = 0; i < n; ++i)
v[i] = static_cast<int>(i);
//shuffle
for (size_t i = n - 1; i > 0; --i)
std::swap(v[i], v[static_cast<size_t>(rand()) % (i + 1)]);
//print
for (size_t i = 0; i < n; ++i)
std::cout << (i > 0 ? "," : "") << v[i];
return 0;
}
Prints, for example:
27,24,2,23,13,6,9,14,11,5,15,18,16,29,22,12,26,20,10,8,28,25,7,4,1,17,0,3,19,21

Can you help me in finding the best algorithm? [duplicate]

The subarray contains both positive and negative numbers. You have to find a maximum sum subarray such that the length of the sub-array is greater than or equal to k.
Here is my code in c++ using Kadane's algorithm.
#include <iostream>
using namespace std;
int main(){
int n,k;
cin >> n >> k;
int array[n];
int sum = 0;
int maxsum = 0;
int beststarts[n];
for(int i = 0;i < n; i++){
cin >> array[i];
}
for(int i = 0;i < k-1;i ++){
sum = sum+array[i];
beststarts[i] = 0;
}
for(int i = k-1;i < n; i++){ //best end search with min length;
sum = sum+array[i];
int testsum = sum;
if(i > 0){
beststarts[i] = beststarts[i-1];
}
for(int j = beststarts[i] ;i-j > k-1;j ++){
testsum = testsum - array[j];
if(testsum > sum){
beststarts[i] = j+1;
sum = testsum;
}
}
if(sum > maxsum){
maxsum = sum;
}
}
cout << maxsum;
return 0;
}
My code is working fine but it is very slow, and i cant think of any ways to improve my code. I have also read this question Find longest subarray whose sum divisible by K but that is not what i want, the length can be greater than k also.
Solution based on this answer
Live demo
#include <algorithm>
#include <iterator>
#include <iostream>
#include <numeric>
#include <ostream>
#include <utility>
#include <vector>
// __________________________________________________
template<typename RandomAccessIterator> typename std::iterator_traits<RandomAccessIterator>::value_type
max_subarr_k(RandomAccessIterator first,RandomAccessIterator last,int k)
{
using namespace std;
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
if(distance(first,last) < k)
return value_type(0);
RandomAccessIterator tail=first;
first+=k;
value_type window=accumulate(tail,first,value_type(0));
value_type max_sum=window, current_sum=window;
while(first!=last)
{
window += (*first)-(*tail) ;
current_sum = max( current_sum+(*first), window );
max_sum = max(max_sum,current_sum);
++first;
++tail;
}
return max_sum;
}
// __________________________________________________
template<typename E,int N>
E *end(E (&arr)[N])
{
return arr+N;
}
int main()
{
using namespace std;
int arr[]={1,2,4,-5,-4,-3,2,1,5,6,-20,1,1,1,1,1};
cout << max_subarr_k(arr,end(arr),4) << endl;
cout << max_subarr_k(arr,end(arr),5) << endl;
}
Output is:
14
11
int w(0);
for (int i=0; i < k; i++) w += a[i];
int run_sum(w), max_sum(w);
for (int i=k; i < n; i++) {
w = a[i] + max(w, w-a[i-k]); // window will such that it will include run_sum
run_sum = max(run_sum + a[i], w);
max_sum = max(run_sum, max_sum);
}
return max_sum;