Divide and Conquer in Algorithm Design and Analysis

1. Introduction to divide and conquer

The divide and conquer method is to decompose a problem of size N into K smaller sub-problems, which are independent of each other and have the same nature as the original problem. The solution to the original problem can be obtained by finding the solution of the subproblem.

1.1 Basic idea

When we solve some problems, because these problems have to deal with a lot of data, or the solution process is quite complicated, the direct solution method takes a long time, or cannot be directly solved at all. For this kind of problem, we often decompose it into several sub-problems first, find the solutions to these sub-problems, and then find a suitable method to combine them into a solution to the whole problem. If these sub-problems are too large to solve, they can be divided into several smaller sub-problems, and so on, until the solution can be found directly. This is the basic idea of ​​the divide and conquer strategy. In general, dichotomy is also used.

Dichotomy method: When using the divide and conquer strategy to solve the problem, the time required depends on factors such as the number of sub-problems after decomposition, the size of the sub-problems, etc., and the dichotomy method is often used because of its simple and uniform characteristics. An efficient method, such as binary search.

1.2 Solution steps

The general steps to solve a problem by divide and conquer are as follows:

(1) Decomposition, which divides the problem to be solved into several smaller-scale similar problems;

(2) Solving, when the sub-problems are divided into small enough, solve them with simpler methods;

(3) Merge. According to the requirements of the original problem, the solutions of the sub-problems are merged layer by layer to form the solution of the original problem.

1.3 specific algorithm

{
    
    //开始
	if(1、问题不可分)
		2、返回问题解;
  	else
  	{
    
    
   		3、从原问题中划分出含一半运算对象的子问题1;
 		4、递归调用分治法过程,求出解1;
 		5、从原问题中划出含另一半运算对象的子问题2;
 		6、递归调用分治法过程,求出解2;
   		7、将解1、解2组合成整个问题的解; 
  	} 
}//结束

1.4 Application scenarios

The problems solved by using the divide and conquer strategy generally have the following characteristics:

1. The original problem can be decomposed into multiple sub-problems. Compared with the original problem, these sub-problems are only reduced in scale, and their structure and solution method are the same or similar to the original problem.

2. In the decomposition process of the original problem, the sub-problems are solved recursively. Since recursion must have a termination condition, when the size of the decomposed sub-problem is small enough, it should be able to be solved directly.

3. After solving and obtaining the solutions of each sub-problem, it should be possible to combine or construct the solution of the original problem in a certain way or method.

It is not difficult to find that in the divide-and-conquer strategy, due to the similarity in structure and solution between the sub-problem and the original problem, most of the problems solved by the divide-and-conquer method adopt the form of recursion . In various sorting methods, such as merge sort, quick sort, heap sort, etc., there is a divide and conquer idea. In addition, the following problems can also be solved with a divide-and-conquer strategy:

Merge Two Sorted Lists (merge two ordered linked lists) - LeetCode 21
Merge k Sorted Lists (merge K ascending linked lists) - LeetCode 23
Top K Question: Top K high-frequency elements - LeetCode 347

2. Binary search

**Problem Description:**Given n elements, which are ordered (assuming ascending order), find a specific element x from them.

**Algorithm idea:** Divide the ordered sequence into two parts of approximately equal size, then compare the middle element with the specific search element x, if x is equal to the middle element, the search is successful, and the algorithm terminates; if x is smaller than the middle element, Then continue to search in the first half of the sequence, that is, repeat the decomposition and governance operations in the first half of the sequence; otherwise, continue to search in the second half of the sequence, that is, repeat the decomposition and governance operations in the second half of the sequence.

algorithm design:

(1) Set the search interval:

int left; // C++自动初始化为0
int right = n;

(2) If the search interval [left, right] does not exist, the search fails and returns; otherwise, execute (3).

(3) Take the middle bit mid = (left + right)/2, compare x with a[mid], there are three situations:

  • If x < a[mid], then right = mid - 1; the search is performed in the left half interval, go to (2);

  • If x > a[mid], then left = mid + 1; the search is performed in the right half interval, go to (2);

  • If x = a[mid], the search is successful and the value of mid is returned.

Time complexity analysis:

(1)顺序查找
- 最好时间复杂度:O(1)
- 最坏时间复杂度:O(n)
(2)二分查找
- 最好时间复杂度:O(1)
- 最坏时间复杂度:O(logn)

Algorithm implementation:

#include <iostream>
#include <vector>

int binarySearch(std::vector<int> nums, int l, int r, int x) {
    
    
    if (l <= r) {
    
    
        // 计算 mid 时需要防止溢出,left+(right-left)/2和(left+right)/2的结果相同,但是有效防止了left和right太大直接相加导致溢出
        int mid = l + (r-l)/2;
        if (nums[mid] == x) {
    
    
            return mid;
        } else if (nums[mid] > x) {
    
    
            return binarySearch(nums, l, mid - 1, x);
        } else {
    
    			 
            return binarySearch(nums, mid + 1, r, x);
        }
    } else {
    
    
        return -1;			
    } 
}

int main() {
    
    
    std::vector<int> nums{
    
    2, 3, 4, 10, 40};
    int x = 10;

    int ans = binarySearch(nums, 0, nums.size() - 1, x);
    if (ans == -1) {
    
    
        std::cout << "未找到该数!" << std::endl;
    } else {
    
    
	    std::cout << "该数的索引为:" << ans << std::endl;
    }

	return 0;
}

Guess you like

Origin blog.csdn.net/crossoverpptx/article/details/131454614