[C++] Algorithm Collection (14): Greedy Algorithm

Insert picture description here

how are you

Greedy algorithm can be understood as a special kind of dynamic programming, with some more special properties, which can further reduce the time complexity of dynamic programming algorithm.

Take a look at a few topics to familiarize yourself with this "Constantly seeking local optima"Algorithm.


Jumping game I

Enter a non-negative integer array nums, the array element nums[i] means: if you stand at position i, you can jump a few steps forward at most.
Now you are standing at the first position nums[0], can you jump to the last position of the array?

Example: [1,2,3,4,5], you can
[1,2,0,0,4], not


Thinking analysis

This question is relatively simple. Of course, don't use backtracking. If you use backtracking, the time complexity is too high.
There are too many ways to succeed, but there is only one way to fail: there are enough 0s lying in it, so that no matter how hard you try, you can’t jump over.

Let's try some of our chestnuts:

[0,····] //点点点的意思是随便你填什么数字都无所谓了
[1,2,1,0,···]
[2,0,0,···]
//还有啥特例吗?

Let's analyze the above chestnut (we assume that the array has -1 grid, nums[-1] = 1, we start from nums[-1]): The
first chestnut: inSubscript is 0When I met a desperate 0, fromSubscript is -1The place was previously able to move forwardMaximum number of steps 1, Unable to cross, end.
The second chestnut: inThe subscript is 3When I met a desperate 0, fromSubscript is 1Places that have been able to move forwardMaximum number of steps 2, Unable to cross, fail.
The third chestnut: inThe subscript is 2When I met a desperate 0, fromSubscript is 0Places that have been able to move forwardMaximum number of steps 2, Unable to cross, fail.

What effective information can we extract from these three chestnuts?

0 --1= 1
3 - 1 = 2
2 - 0 = 2

Right.
anything else? Why don't you pass it, for example, in Example 2, you don't pass the point with the subscript 2 to transfer it? Because the transfer is also invalid.

That means we are going to try to transfer.

It may be a little confusing to say that, I will change the example 2: [1,2,2,0], won't this be alive!

Let’s compare the two examples 2:
(Use flag to record the farthest distance that can be reached at the moment)

[1,2,1,0,···]	
//下标0最多到下标1,flag = 1;下标1最多到下标3,flag = 3;下标2最多到下标3,flag = 3;下标3,flag = 3;卒
[1,2,2,0]		
//下标0:flag = 1;下标1:flag = 3;下标2:flag = 4

It can be seen that when flag == subscript, it is cold.


Code

So, we write the code:

bool canJump(vector<int>& nums){
    
    
	int n = nums.size();
	int farthest = 0;
	for(int i = 0; i < n-1; i++){
    
    
		//不断计算能够跳到的最远距离
		farthest = max(farthest,i+nums[i]);
		//如果碰到0跳不动了
		if(farthest  <= i) return false;
	}
	return farthest >= n-1;
}

Jump game II

Same as above, but this time you are guaranteed to jump to the end, and ask you to jump at least a few times.

Looks so familiar, it seems that I wrote a question like this before. Change coins, right?

De-recursively selecting the best in the subsequent jump method belongs to a kind: the backward-to-forward solution method can be understood as traversing a tree sequentially from the bottom layer. It's just that we pruned the tree through a memo, otherwise we really couldn't bear to look directly at it.

However, what we are talking about today is the greedy algorithm, which can be imagined as going one way from top to bottom. let us see:


Ideas

What is the greedy algorithm? The greedy algorithm will choose the most promising step at the moment.
For example: [2,3,1,2,5,1]
When you are at the position of subscript 0, you can skip two steps. In the case of recursion, it will recursively calculate the optimal number of steps from these two steps to the final result, but the greedy algorithm does not.
Does the greedy algorithm hop as many times as possible? NoNoNo, choose the most potential at the moment: at the position of coordinate 1, you have three choices; at the position of coordinate 2, you have only one choice, so the greedy algorithm will let you choose to jump to coordinate 1. This is the local optimization of the greedy algorithm (don't think about counterexamples, if you want to use the greedy algorithm, you have to bear its error rate).

Next, let's write the code:

int jump(vector<int>& nums){
    
    
	int n = nums.size();
	//站在索引i,最多能跳到索引end
	int end = 0;
	//从索引【i···end】起跳,最远能到的距离
	int farthest = 0;
	//纪录跳跃次数
	int jumps = 0;
	for(int i = 0; i<n; i++){
    
    
		farthest = max(nums[i]+1,farthest);
		if(end == i){
    
    
			jumps++;
			end = farthest;
		}
	}
	return jumps;
}

The right middle finger is numb. .
Take a rest.

Insert picture description here

Guess you like

Origin blog.csdn.net/qq_43762191/article/details/114147353