Divide and conquer and recursion

Divide and conquer and recursion

Recursion is a method;

Divide and conquer is an idea;

Divide and conquer can be implemented with recursion or without recursion

Common divide and Conquer: the solutions at all levels of divide and conquer are different 

Recursive divide and Conquer: the solutions of all levels of divide and conquer are the same

Divide and conquer

The basic idea of partition

Divide and conquer algorithm is to divide a large problem that is difficult to be solved directly into some small-scale same problems, so as to break them one by one, divide and conquer them.
If the original problem can be divided into k subproblems, 1 < K ≤ n, and these subproblems can be solved, and the solution of the original problem can be obtained by using the solution of these subproblems, then this divide and conquer method is feasible.
The subproblems generated by divide and conquer are often the smaller patterns of the original problem, which provides convenience for the use of recursive technology.
In this case, the repeated application of divide and conquer can make the sub problem consistent with the type of the original problem, but its scale continues to shrink, and finally make the sub problem easy to find its solution directly.
This naturally leads to recursive processes.

The problems that divide and conquer can solve have the following characteristics

1) The problem can be easily solved if the scale is reduced to a certain extent

2) The problem can be decomposed into several smaller same problems, that is, the problem has the property of optimal substructure.

3) The solutions of the subproblems decomposed by the problem can be combined into the solutions of the problem;

4) The subproblems decomposed by the problem are independent of each other, that is, there are no common subproblems between subproblems.

The first feature is that most problems can be satisfied, because the computational complexity of the problem generally increases with the increase of the problem scale;

The second feature is the premise of applying divide and conquer, which can be satisfied by most problems. This feature reflects the application of recursive thought;

The third feature is the key. Whether the divide and conquer method can be used completely depends on whether the problem has the third feature. If it has the first and second features but does not have the third feature, the greedy method or dynamic programming method can be considered.

The fourth feature relates to the efficiency of the divide and conquer method. If each sub problem is not independent, the divide and conquer method needs to do a lot of unnecessary work and repeatedly solve the common sub problems. At this time, although the divide and conquer method can be used, it is generally better to use the dynamic programming method.

Steps and design patterns

step

Decomposition: decompose the original problem into several small-scale, independent sub problems with the same form as the original problem;
Solution: if the subproblem is small and easy to be solved, solve it directly, otherwise solve each subproblem recursively;
Merge: merge the solutions of each sub problem into the solutions of the original problem.

Design pattern

Divide-and-Conquer(P)
    1. if |P|≤n0
    2. then return(ADHOC(P))
    3. take P Decompose into smaller subproblems P1 ,P2 ,...,Pk
    4. for i←1 to k
    5. do yi ← Divide-and-Conquer(Pi) △ Recursive solution Pi
    6. T ← MERGE(y1,y2,...,yk) △ Merge subproblem
    7. return(T)

Where | P | represents the scale of problem p;

n0 is a threshold, which means that when the scale of problem P does not exceed n0, the problem is easy to be solved directly, and there is no need to continue decomposition.

ADHOC § is the basic sub algorithm of the divide and conquer method, which is used to directly solve the small-scale problem P. Therefore, when the scale of P does not exceed n0, it is directly solved by the algorithm ADHOC §.

The algorithm MERGE(y1,y2,..., yk) is a merging sub algorithm in the divide and conquer method, which is used to merge the corresponding solutions y1,y2,..., yk of the sub problems P1, P2,..., Pk of P into the solutions of P.

practice

1. Merge sort

analysis

Stages can be understood as the process of recursively disassembling molecular sequences. The recursion depth is log2n.  

Let's look at the treatment stage. We need to combine two ordered subsequences into an ordered sequence,  
For example, for the last merge in the figure above, you need to[4,5,7,8]and[1,2,3,6]Two ordered subsequences,  
Merge into final sequence[1,2,3,4,5,6,7,8]


code

import java.util.Arrays;

public class MergeSort {
    public static void main(String []args){
        int []arr = {9,8,7,6,5,4,3,2,1};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void sort(int []arr){
        int []temp = new int[arr.length];//Before sorting, build a temporary array whose length is equal to the length of the original array to avoid frequently opening up space in recursion
        sort(arr,0,arr.length-1,temp);
    }
    private static void sort(int[] arr,int left,int right,int []temp){
        if(left<right){
            int mid = (left+right)/2;
            sort(arr,left,mid,temp);//Merge and sort on the left, so that the left subsequence is orderly
            sort(arr,mid+1,right,temp);//Merge and sort on the right, so that the right subsequence is orderly
            merge(arr,left,mid,right,temp);//Merge two ordered subarrays
        }
    }
    private static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i = left;//Left sequence pointer
        int j = mid+1;//Right sequence pointer
        int t = 0;//Temporary array pointer
        while (i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                temp[t++] = arr[i++];
            }else {
                temp[t++] = arr[j++];
            }
        }
        while(i<=mid){//Fill the remaining elements on the left into temp
            temp[t++] = arr[i++];
        }
        while(j<=right){//Fill the remaining elements of the right sequence into temp
            temp[t++] = arr[j++];
        }
        t = 0;
        //Copy all the elements in temp to the original array
        while(left <= right){
            arr[left++] = temp[t++];
        }
    }
}

Tags: Python Algorithm Machine Learning

Posted on Mon, 22 Nov 2021 14:03:17 -0500 by trg