31

Dynamic programming gives you a way to think about algorithm design. This is often very helpful. Memoization and bottom-up methods give you a rule/method for turning recurrence relations into code. Memoization is a relatively simple idea, but the best ideas often are! Dynamic programming gives you a structured way to think about the running time of your ...


12

Your understanding of dynamic programming is correct (afaik), and your question is justified. I think the additional design space we get from the kind of recurrences we call "dynamic programming" can best be seen in comparison to other schemata of recursive approaches. Let's pretend our inputs are arrays $A[1..n]$ for the sake of highlighting the concepts. ...


11

There is no general way to do this. The "space of algorithms" is not a nice one, with a natural metric or other nice properties, unlike e.g. the real numbers. Note that even in the case of trying to solve $f(x)=0$, where your search space is $\mathbb{R}$, most algorithms work under several assumptions on $f$, e.g. continuity (there is no algorithm which can ...


8

Intuitively, a kernelization algorithm is an algorithm which in polynomial time preprocesses a given instance and outputs an instance whose size is bounded in the parameter. The goal of kernelization is (at least) two-fold. We get provable performance guarantees, i.e., we can prove upper bounds on the output instance, which has applications both in the ...


8

If you have only one life only safe way is to check every element starting from minimal. It's $O(n)$ If you have two lives and limited with $k + 1$ comparisons the minimal element of array you can check first has index $k$, so we still have $k$ comparisons to check all previous elements one by one, if no lives was lost than next element to check has index $...


7

SHA1 or SHA256, whichever you use, is for any practical purpose a random function. What you are observing is that random allocation is not as good as deterministic allocation. If you knew all the values in advance then you could indeed arrange that each cell would get exactly the same number of hits. Unfortunately, when you throw $n$ balls into $k$ bins, the ...


6

Dynamic Programming allows you to trade memory for computation time. Consider the classic example, Fibonacci. Fibonacci is defined by the recurrence $Fib(n)=Fib(n-1)+Fib(n-2)$. If you solve using this recursion, you end up doing $O(2^n)$ calls to $Fib(\cdot)$, since the recursion tree is a binary tree with height $n$. Instead, you want to calculate $Fib(2)$...


6

Here is another slightly different way of phrasing what dynamic programming gives you. Dynamic programming collapses an exponential number of candidate solutions into a polynomial number of equivalence classes, such that the candidate solutions in each class are indistinguishable in some sense. Let me take as an example the problem of finding the number of ...


6

Your problem is known as Multi-Capacity Bin Packing. One of the foundational papers in the area is by Leinberger, Karypis and Kumar, who state a result of Garey, Graham, Johnson and Yao that in the case of $d$ constraints (in your case, $d = n$) many natural algorithms give a $d+1$-approximation.


6

There is no such thing as the correct generalization of the greedy selection technique, because it's an informal technique. That said, there has been some effort at modeling the greedy heuristic, with a view toward understanding its limitations. This study has been initiated by Borodin, Nielsen and Rackoff, (Incremental) priority algorithms, and continued ...


6

The simple implementation idea is to separate the values into three groups: values less than the pivot, values equal to the pivot, and values greater than the pivot. In pseudocode, the algorithm looks like the following. algorithm quicksort(A, lo, hi): if lo < hi then p ← pivot(A, lo, hi) left, right ← three-way-partition(A, p, lo, ...


5

Store the elements as a sequence, sorted by increasing timestamp. Use binary search to find the location where $\tilde{t}$ would occur if it were in the array; then you can easily find the two neighboring elements. Finding the two neighboring elements can be done in $O(\lg n)$ time. You'll also need to be able to append to the end of the sequence and ...


5

You are on a good path, but seem to be confused for no reason. After step 2 you have created an array with average scores. This is a worst case O(N) size array. What is the complexity of finding the highest average score now? Do you need to sort the array?


4

Suppose you have an array $A = [e^0, e^1, e^2, \dots]$. You do a search in this array, and try to find the biggest value in the array that's smaller than or equal to $x$. You find this value at position $n$. What is the value of $A[n]$? What can you say about $\ln(x)$ in relation to $n$? Can you find the correct $n$ quickly? Does it help that $A$ is sorted?


3

Let's try to solve a simpler problem first: Given an array that only has 1's and 0's in it, the method turns every number into the amount of 'steps' it is away from the closest 0 to the left. Now this problem is easy. A simple solution is: traverse the array from left to right, keeping track of the distance from the last zero encountered and updating each ...


3

Actually, people do commonly use reductions for both purposes: both for proving lower bounds, and for designing algorithms to handle a certain problem. For instance, it's very common to reduce a problem to linear programming, to a max-flow problem, or to another well-studied problem. This is using reductions for solving problems. Any particular textbook ...


3

One approach would be to randomly pick a large constant $k$ indices and test them. The exact probability of at least one of them being $A[i] = X$ would be: $$\begin{align} P(\text{at least }1\; X) &= 1 - P(\text{all are } Y)\\ & = 1 - \left(\frac{n/3}{n}\cdot \frac{n/3-1}{n-1}\cdot \ldots \cdot \frac{n/3 - (k-1)}{n - (k-1)}\right)\\[0.5em] & \...


2

The big advantage of Lempel-Ziv-style compression is that it creates its own dictionary on the fly and tailors it to the data. Therefore, they are general-purpose compression algorithms which can be used without having to keep dictionaries in sync; all you need for decoding is the encoded file and the algorithm. If you fix a dictionary, this is going to ...


2

A naive solution could be that each general first launch a binary counter in its row and counts the current time until $k\log(k)$ steps and then run the FSSP. To do this you just need to detect the value of $k$ and compute $k\log(k)$ in less than $k\log(k)$ steps: sending a signal back and forth toward the other end while incrementing a binary counter gives ...


2

If $v$ is NIL then transplanting $v$ just transplants an empty tree. This is fine. It is handled in the exact same way as transplanting an actual tree, the only difference being that we don't need to update $v$'s parent pointer. Could the code be structured differently? Probably. Why, then, did the authors choose this particular implementation? No deep ...


2

The answer for your question How to improve with an implementation that would be based on saving computed values in an array? is to use memoization (sometimes known as dynamic programming), which incidentally is the same as saving computed values. But this is a somewhat odd solution to the problem. A better solution is computing the binomial coefficient ...


2

TL;DR Divide and concur doesn't have any rigorous definition. So any argument you make for or against will be just an emotional argument. The situation is made worse by the fact that the task accomplished by this algorithm doesn't need D&C. So, the answer is "probably". Long version One scenario where it would make sense to use D&C in ...


2

You should look into DFS and BFS, which can solve this problem in $O(n+m)$ time where $n$ is the number of nodes and $m$ is the number of edges. The performance of the algorithm you described is much worse than you think, because you potentially have to relabel nodes many times. Consider the edges presented in this order: $v_{2k},v_{2k+1}$ $\vdots$ $v_2, ...


2

The need to define reduction formally arises only when defining classes of hard problems. Consider polynomial time reducibility as an example. The same notion is used for both "positive" and "negative" purposes: If a problem $A$ can be solved in polynomial time and there is a polynomial time reduction from problem $B$ to problem $A$, then $B$ can also be ...


2

I've seen reduction used implicitly. A good example is the problem of finding a maximum spanning tree. In that case, you reduce the problem to the minimum spanning tree problem by multiplying all edge weights by -1, then apply Prim's or Kruskal's algorithm to the new graph. In this case, reduction was used to "rephrase" the problem in a slightly different ...


2

If you only want to find all rational roots, you can simply use the rational root theorem. This theorem states that, given a polynomial $a_n x^n + a_{n-1}x^{n-1} + \ldots + a_1x+a_0$, for any rational root $x=p/q$, where $p,q\in \mathbb N$ and $GCD(p,q)=1$, we have: $p$ is a divisor of $a_0$ and $q$ is a divisor of $a_n$. So, one possible algorithm is to ...


2

The paper Computing Real Roots of Real Polynomials by Sagraloff and Mehlhorn from 2015 provides an almost optimal algorithm and references for simpler algorithms that might be used in practice. The CGAL library (in version 4.9) for example uses the method developed by Arno Eigenwillig in his PhD thesis Real Root Isolation for Exact and Approximate ...


2

Just some hints that will tell you how to solve it efficiently: If you know where the first zero is, then you know what numbers to write down at all positions before and up to that zero. For example, if a [4] is the first zero, then you know the numbers for positions 0, 1, 2, 3 and 4 (4, 3, 2, 1, 0). You don't know the number for position 5 at this point. ...


2

Perhaps this is too broad a question for a coherent answer, so let me first try to say something about line segment intersection, at least. The main reason the sweep-line algorithm is efficient is that we only have to worry about neighboring line segments. We can generalize this procedure to $\mathbb{R}^n$ by noting that if we sweep a line over a sub-plane ...


2

You have a sorted array of n elements. If the first element is > k then no elements have absolute value ≤ k. (Why ?) If the last element is < -k then no elements have absolute value ≤ k. (Why ?) If the first element is ≥ -k and the last element is ≤ k then all n elements have absolute value ≤ k. (Why ?) If neither of these criteria was fulfilled then ...


Only top voted, non community-wiki answers of a minimum length are eligible