Greedy algorithm C++ puzzle (leetcode101 (biscuit allocation 455 (candy allocation 135) (interval problem 435)

Keywords: C++ Algorithm leetcode pointer greedy algorithm

Basic Ideas:
Local Optimal - >Global Optimal
Difficulty: Determine the best "what object"

Simple questions:

Find money: a total of x Yuan with a minimum of several pieces of money 100 yuan 50 yuan 10 yuan 5 yuan 1 yuan
Idea: x divides 100, 50, 20, 10, 5, 1
Integer division adds up

leetcode

455 Allocate cookies

Suppose you're a great parent and you want to give your children some cookies. However, each child can only give one cookie at most.
For each child i, there is an appetite value g[i], which is the minimum size of cookies that will satisfy their appetite. And each biscuit J has a size s[j]. If s[j] >= g[i], we can assign this cookie J to child i, and the child will be satisfied. Your goal is to satisfy as many children as possible and output the maximum number.

 int findContentChildren(int* g, int gSize, int* s, int sSize) {

        //sort from small to large
        for (int i = 0; i < gSize; i++) {
            for (int j = i + 1; j < gSize; j++) {
                if (*(g + i) > *(g + j)) {
                    int mid;
                    mid = *(g + i);
                    *(g + i) = *(g + j);
                    *(g + j) = mid;
                }
            }
        }
        for (int i = 0; i < sSize; i++) {
            for (int j = i + 1; j < sSize; j++) {
                if (*(s + i) > *(s + j)) {
                    int mid;
                    mid = *(s + i);
                    *(s + i) = *(s + j);
                    *(s + j) = mid;
                }
            }
        }
        //match
        int matchNum = 0;
        for (int i = 0; i < gSize; i++) {
            for (int j = 0; j < sSize; j++) {
                if (*(g + i) <= *(s + j)) {                    
                    matchNum++;
                    i++;
                    *(s + j) = 0;
                    if (i == gSize) {
                        break;
                    }
                }
            }
        }

        return matchNum;
    }

Source: LeetCode
Links: https://leetcode-cn.com/problems/assign-cookies
Copyright shall be owned by the withholding network. For commercial reprinting, please contact the official authorization. For non-commercial reprinting, please indicate the source.

135 Distributing Candy

Teachers want to distribute candy to children. N children stand in a straight line. Teachers will pre-rate each child based on their performance.
You need to help teachers distribute candy to these children as follows:
Each child is assigned at least one candy.
A child with a higher score must get more candy than his neighbour on either side.
So how many candies does the teacher need to prepare at least?

Ideas:

This is a classic question that requires left and right traversals of ratings to achieve local optimum (children with higher ratings must get more candy than their neighbors on either side).

  1. Set all candy values to 1 to ensure that each child has candy

    • Traverse ratings left, and if ratings[i+1]>ratings[i], make candy[i+1]=candy[i]+1
    • Right traverse ratings, if ratings[i-1]>ratings[i], then ratings[i-1]=max(ratings[i-1],
      Ratings[i]+1!!! Error prone
    • Summing candy with the accumulate function

    Note the value set by the for loop and the direction of the "ratio size" when traversing

Involving grammar

int sum = accumulate(vec.begin() , vec.end() , 42);

accumulate takes three parameters: the first two specify the range of elements to be accumulated, and the third parameter is the initial value of the accumulation.

class Solution {
public:
   int candy(vector<int>& ratings) 
{
	int num = ratings.size();
	vector<int> candy(num, 1);
	for (int i = 0; i < num - 1 ; i++) {
		if (ratings[i + 1] > ratings[i]) {
			candy[i + 1] = candy[i] + 1;
		}
	}
	for (int i = num - 1; i > 0; i--) {
		if (ratings[i - 1] > ratings[i]) {
			candy[i - 1] = max((candy[i] + 1),candy[i - 1]);
		}
	}
	int total = accumulate(candy.begin(), candy.end(), 0);
	return total;
}
};

435 Interval Problem

Given a set of intervals, find the minimum number of intervals that need to be removed so that the remaining intervals do not overlap each other. Note: It can be assumed that the end point of an interval is always greater than its start point. The boundaries of the intervals [1,2] and [2,3] touch each other but do not overlap each other.

Ideas:

It is important to understand the meaning of the topic. "Minimum quantity" means that it is entirely wrong to simply judge whether a set intersects another set or whether a set is a subset of another set.

Idea Derivation

  • Since this is a greedy problem, it must involve local optimum to global optimum. So the problem can be translated into finding what is the local best.

  • Because greedy algorithms always have left and right traversals, this question must be sorted.

  • Role of sorting: Arranging the intervals from smallest to largest at the right endpoint ensures that more space is left for other intervals (that is, more intervals are not coincident with the previous intervals).

  • Recording the number of intervals to remove: Because the right endpoints of each interval are arranged from small to large, you only need to determine if the left endpoint of interval i+1 is smaller than the right endpoint of interval I. If so, overlap_num++; If not, the interval i+1 does not coincide with the interval i, and the right endpoint of the interval i+1 is compared with the left endpoint of the interval i+3.

Involving grammar

1. void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
The second parameter last: is the end address (the address of the last data after the last data)
The return value of the comp function is a bool variable: used to determine whether the first two variables are swap
2. Constant Reference Pass By Reference Pass By Value Pass By Share

I can't submit it it because I timed out! After a few small changes, the code efficiency is greatly improved. Consult my C Language Consultant 🐟 Mr. A later discovered that there was a problem with passing constant references by reference by value. C++ is really amazing!
Constant reference:
Pass by value:
A parameter is a copy of an argument (it is created in stack memory and its value is copied), and the stack memory is automatically cleared after the function is executed. Therefore, from the point of view of the called function, the value transfer is one-way, and the parameter cannot change the argument.
Pass Value==Pass Memory Copy
Pass by reference:
&Represents a reference argument
The obj within a function points to the same block of memory that was created when the variable was defined before the function was called. Any changes made to this parameter will be reflected in the externally defined obj1 variable
Pass-by Reference==Pass-by Memory Pointer
Delivery by Share

Pass By Share==Pass Referenced Copy

	//Submittable Version
	auto num = intervals.size();
	auto overlap_num = 0;
	sort(intervals.begin(), intervals.end(), [](const vector<int> & a, const vector<int> & b) {return a[1] < b[1]; });
	//Timeout version
	auto num = intervals.size();
	int overlap_num = 0;
	sort(intervals.begin(), intervals.end(), [](vector<int> a, vector<int> b) {return a[1] < b[1]; });
class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
	if (intervals.empty()) {
		return 0;
	}
	auto num = intervals.size();
	auto overlap_num = 0;
	sort(intervals.begin(), intervals.end(), [](const vector<int> & a, const vector<int> & b) {return a[1] < b[1]; });
	int prev = intervals[0][1];
	for (int i = 1; i < num; i++) {
		if (intervals[i][0] < prev) {
			overlap_num++;
		}
		else {
			prev = intervals[i][1];
		}
	}
	return overlap_num;
}
   
};

Posted by amreiff on Sun, 21 Nov 2021 10:53:40 -0800