Home > Software design >  Bounds of rotations
Bounds of rotations

Time:04-14

Does anyone know how to solve this problem? It is easy to code this out to work in O(n^2) time complexity where you simply calculate the value of all possible combinations, but I'm unable to come up with an O(n) time complexity solution.


Given a list of integers x and a constant c, find the rotations of the list with the highest value and the lowest value respectively, where formula is:

enter image description here

and weights w = c^i, 0.2 <= c <= 0.8.

For example,

Input: x = [2,5,6,8] c = 0.8

Then possible rotations are

  • 2 * 0.8**0 5 * 0.8**1 6 * 0.8**2 8 * 0.8**3 <-- Lowest value (13.936)
  • 5 * 0.8**0 6 * 0.8**1 8 * 0.8**2 2 * 0.8**3
  • 6 * 0.8**0 8 * 0.8**1 2 * 0.8**2 5 * 0.8**3 <-- Highest value (16.24)
  • 8 * 0.8**0 2 * 0.8**1 5 * 0.8**2 6 * 0.8**3

Return: (13.936, 16.24)

Solve it in O(n) time complexity.


Here's my code:

def bounds_of_rotations(x,c):
    """ Time complexity of this method is O(n^2) since we are going through a list of size n for n times. 
    """
    upper_bound = ''
    lower_bound = ''
    
    for i in range(0,len(x)):
        value = 0
        for j in range(0, len(x)):
            index = (i j) % len(x)
            value  = x[index] * c**j
            
        if i == 0 or value > upper_bound:
            upper_bound = value
        if i == 0 or value < lower_bound:
            lower_bound = value
    
    return (lower_bound, upper_bound)

CodePudding user response:

There is a O(n) algorithm effectively. The idea is to build an array of size 2*n - 1:

{1*X[0] C*X[1] C^2*X[2] ... C^n-1*X[n-1] C^n*X[0] C^n 1*X[1] ... C^(2*n-2)* X[n-2]}

and to perform on it a sliding window sum calculation, wich can be implemented in O(2*n) = O(n).

The expected dot products are equal to the running sums, up to a weighting factor C^k.

Here is a simple C implementation, that could be easily transposed in any language.

#include <iostream>
#include <vector>
#include <utility>

std::pair<double, double> min_max_rotation (const std::vector<int>& X, double C) {
    int n = X.size();
    double vmin = 0.0, vmax = 0.0;
    double coef = 1.0;
    double sum = 0.0;
    std::vector<double> Xweighted (2*n);
    for (int i = 0; i < n;   i) {
        Xweighted[i] = X[i] * coef;
        sum  = Xweighted[i];
        coef *= C;
    }
    vmin = vmax = sum;
    double factor = C;
    for (int i = 0; i < n-1;   i) {
        Xweighted[i n] = X[i] * coef;
        coef *= C;
        sum  = (Xweighted[i n] - Xweighted[i]);
        double dot_product = sum / factor;
        factor *= C;
        if (dot_product < vmin) vmin = dot_product;
        if (dot_product > vmax) vmax = dot_product;
    }
    return {vmin, vmax};
}

int main() {
    std::vector<int> X = {2, 5, 6, 8};
    double C = 0.8;
    auto [vmin, vmax] = min_max_rotation (X, C);
    std::cout << vmin << "   " << vmax << "\n";
    return 0;
}
  • Related