Recursion, divide and conquer and dichotomy

One, recursion

1 Introduction

We call this function in a custom function, which is recursive.
It is divided into two types:

  1. Function a calls function a (direct recursion)
  2. Function a calls function b, function b calls function a (indirect recursion)

Obviously the function will be called continuously when it is called, so the recursive function roughly consists of two parts

  1. Function exit part
  2. Call function part

Give a simple example:
find the factorial of n

n Result (f(n)) Result (f(n))
n=5 (call function) f(5)=5*f(4) 5*24=120
n=4 (call function) f(4)=4*f(3) 4*6=24
n=3 (call function) f(3)=3*f(2) 3*2=6
When n=2 (call function) f(2)=2*f(1) 2*1=2
When n=1 (function exit) f(1)=1 1

ps: When calling a recursive function, the computer will call the stack space, so please be careful with the number of recursive layers! In order to avoid MLE
ps: When calling a function, the function will first go to the bottom layer and find the final result, so please be careful about the number of recursions! So as to avoid TLE

The function is as follows:

int func(int n) {
    
    
//递归出口 
	if(n<=1) return 1;//0!=1
//调用函数 
	return func(n-1)*n;
}

2. Examples

①, find the greatest common divisor

Memory limit: 128 MiB
Time limit: 1000 ms
Title description:
Use a recursive algorithm to find the greatest common divisor of two numbers m and n. (M>n>0)
Sample input:
8 6
Sample output:
gcd=2
Analysis:
We can use recursion to achieve the tossing and dividing method

  1. Function exit part: return n when it can be divisible
  2. Call function part: return the greatest common factor of the divisor and remainder The
    function is as follows:
int gcd(int m,int n) {
    
    
	if(! m % n) return n;
	return gcd(n, n % m);
}

②, full arrangement

Memory limit: 128 MiB
Time limit: 1000 ms
Title description:
Given a string composed of different lowercase letters (length <10), output all permutations of this string. We assume that there are'a' <'b' <… <'y' <'z' for lowercase letters, and the letters in the given string have been arranged in ascending order.
Sample input:
abc
Sample output:
abc
acb
bac
bca
cab
cba
Analysis:
We can use the first few letters as parameters, and use this as a recursive export.
Other times we look for unused characters from the entire string . And store it in the array to be output.

Main code:

int n;//记录字符串长
bool a[10];//记录字符状态
char s[30],//记录输入的字符串
	ans[10];//记录一种可行解
void f(int m) {
    
    
	if(m==n) {
    
    //出口
		cout<<ans<<'\n';//输出答案
		return;//结束函数
	}
	for(int i=0;i<n;i++) {
    
    //从整个字符串中寻找
		if(a[i]==false) {
    
    //用数组记录状态
			ans[m]=s[i];//记录答案
			a[i]=true;//标记为使用过
			f(m+1);//长度+1,继续枚举答案
			a[i]=false;//(找到答案后)重新找下一种答案,而该字符则标记为未使用
		}
	}
}
int main() {
    
    
	cin>>s;//输入
	n=strlen(s);//计算长度
	f(0);//递归
	return 0;
}

Second, divide and conquer

1 Introduction

Generally speaking, divide and conquer is to decompose an original problem into several sub-problems, then solve the sub-problems one by one, and finally merge the solutions of the sub-problems into the solutions of the original problem.
Divide and conquer
Take a chestnut:
Enter a sequence and find the maximum and minimum values.
Don't think so much, let's think about it first: What is the sub-problem? How does he solve it?
Obviously, when the sequence length is one, the maximum value can be known immediately.
In general, you only need to know the maximum value of a number of subsequences to know the maximum value of the sequence.
code show as below:

int fmax(int l,int r) {
    
    
	if(l==r) return a[l];//序列长度为一,返回序列中的唯一元素
	return max(fmax(l,(l+r)/2),fmax((l+r)/2+1,r));//左边的最小值 和 右边的最大值 的 最大值
}
int fmin(int l,int r) {
    
    
	if(l==r) return a[l];//序列长度为一,返回序列中的唯一元素
	return min(fmin(l,(l+r)/2),fmin((l+r)/2+1,r));//左边的最小值 和 右边的最小值 的 最小值
}

2. Sample questions (quick power)

Memory limit: 256 MiB
Time limit: 1000 ms
Title description:
Calculate the value of a b
Sample input:
2 10
Sample output:
1024
Analysis: The
function recursive method is as follows:

Created with Raphaël 2.2.0 f(a,b) b==1 return a b%2==1 return a^(b/2)^2*a return a^(b/2)^2 yes no yes no

Three or two points

1 Introduction

Divide , literally means the method of dividing into two. That is, a problem is divided into two, and the solution of the problem is solved in an appropriate sub-problem (interval).
For example:
in a non-descending sequence, find a given value.
Input format: The
first line contains an integer n, which is a non-descending sequence length. 1<=n<=100000.
The second line contains n integers, is nondecreasing sequence elements. The size of all elements is between 0-1,000,000,000.
The third line contains an integer m, which is a given value. The size of the given value is between 0-1,000,000,000.
Output format:
one character,'Y' means there is a given value in the sequence,'N' means the opposite is the
two-way idea:
First, if there is only one element left in the sequence (l==r), return whether the element is equal to the given value ( a[l]==t).
Then, dichotomy from the middle.
Because the sequence is ordered , we dichotomize the sequence. If the given value is greater than the number in the middle of the sequence (a[(l+r)/2]>t), then go to the left subinterval (l,( l+r)/2-1) , otherwise, look for the right interval ((l+r)/2+1,r) .
such as:

1 2 3 5 7

Find the number 2 The
range of the first search is 1~5;
the interval of the second search is 1~2;
the interval of the third search is 2~2 (found)

2. Examples

Number sequence segmentation
Memory limit: 512 MiB
Time limit: 1000 ms
Title description:
For a given length n positive integer sequence a, it is now to be divided into m segments, and each segment is required to be continuous, and the maximum sum of each segment The value is the smallest.
Sample input:
5 3
4 2 4 5 1
Sample output:
6
Analysis:
get the question The
first thing: find l and r. That is, the scope of the problem.
At least it may be the maximum value of the elements in the sequence; at
most it may be the sum of the elements in the sequence.

cin>>n>>m;
for(int i=1;i<=n;i++) {
    
    
    cin>>a[i];
    l=max(l,a[i]),r+=a[i];
}

The second thing: find the dichotomous condition.

bool f(int x) {
    
    
    int sum=1,t=0;//在传入的限定的最大值中累计需要的区间数量
    for(int i=1;i<=n;i++)
        if(t+a[i]<=x) t+=a[i];
        else sum++,t=a[i];
    return sum<=m;//传回是否符合要求
}

The third thing: find a dichotomy.
Dichotomous maximum value.

while(l<=r) {
    
    
	int mid=(r+l)/2;
	if (f(mid))
		ans=mid,r=mid-1;
	else l=mid+1;
}

Four, summary

Recursion, divide and conquer, and dichotomy all use functions to call themselves to find the answer. It can return the value you need through the execution method you design, and the loop structure written with it will be more concise .
I hope you will learn more about functions after passing this article.

Guess you like

Origin blog.csdn.net/weixin_49692699/article/details/114878004