Force deduction method 1705 - maximum number of apples to eat

Posted by Atari on Wed, 29 Dec 2021 21:50:10 +0100

Original title link: Force buckle


Description:

There is a special apple tree, which can grow several apples every day for n days. On day I, apples[i] will grow on the tree. These apples will rot and become inedible after days[i] (that is, on day i + days[i]). It is also possible that new apples will not grow on the tree for a few days. At this time, it is shown by apples[i] == 0 and days[i] == 0.

You plan to eat up to one apple a day to ensure balanced nutrition. Note that you can continue to eat apples after this n day.

Give you two integer arrays of length n, days and apples, and return the maximum number of apples you can eat.

Example 1:

Input: apples = [1,2,3,5,2], days = [3,2,1,4,2]
Output: 7
Explanation: you can eat 7 apples:
-On the first day, you eat the apples that grow on the first day.
-The next day, you eat an apple that grows the next day.
-On the third day, you eat an apple that grows the next day. After this day, the apples that grew on the third day had rotted.
-From the fourth day to the seventh day, you eat the apples that grow on the fourth day.
Example 2:

Input: apples = [3,0,0,0,2], days = [3,0,0,0,2]
Output: 5
Explanation: you can eat five apples:
-From the first day to the third day, you eat the apples that grow on the first day.
-Don't eat apples on the fourth and fifth days.
-On the sixth and seventh days, you eat apples that grow on the sixth day.

Source: LeetCode
Link: https://leetcode-cn.com/problems/maximum-number-of-eaten-apples
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

Problem solving ideas:

We can make it clear that there are two apples, so we must eat the one that expires earlier.

*There are many concepts involved in this problem.
*First, we build a collection to store all the uneaten apples, including the apples of the day.
*In this way, we can judge whether there are qualified apples in this collection every day. And remove the expired.
*It's OK to experiment simply according to this idea, but the time complexity is too high, so we need to optimize it.
*Optimization 1: I originally took each apple as the unit of objects in this collection, but in practice, the number of list s is too large, so we should build an AppleNode object based on the daily apple as the unit to represent the apple of the day. In this way, fewer objects are traversed.
*Optimization 2: before, the collection objects were arranged in disorder, so they have to be traversed every time, which is very expensive. So change it to order. The earlier the apple expires, the later it is arranged in the collection. In this way, we only need to take those that expire earlier each time.
*
*The traversal array length is n, and the binary tree traverses log(length), so the time complexity is n*log(length),

code:

 public int eatenApples(int[] apples, int[] days) {
        int num = 0;
        List<AppleNode> list = new ArrayList<>();//The list is ordered from large to small according to the end time, and the last one is remove d each time
        for (int index = 0; ; index++) {
            if (index < apples.length) {
                //Avoid repeated judgment
                AppleNode appleNode = new AppleNode();
                appleNode.index = index;
                appleNode.day = days[index] - 1;//Subtract current
                appleNode.num = apples[index];
                appleNode.overdue = index + appleNode.day;
                middel2Insert(list, appleNode);
            }
            if (removeLast(index, list)) {
                num++;
            }
            if (index >= apples.length && list.size() == 0) {
                break;
            }
        }
        return num;
    }

    private boolean removeLast(int day, List<AppleNode> list) {
        //Find the fastest expired when traversing
        while (true) {
            int i = list.size() - 1;
            if (i < 0) {
                return false;
            }
            AppleNode last = list.get(i);
            int surplusDay = last.overdue - day;
            if (surplusDay < 0) {
                list.remove(i);
                continue;
            }
            if (last.num > 0) {
                last.num--;
                if (last.num == 0) {
                    list.remove(i);
                }
                return true;
            }
            return false;
        }
    }


    /**
     * Binary search insert
     * overdue The small one is in the back
     *
     * @param node
     */
    public void middel2Insert(List<AppleNode> list, AppleNode node) {
        if (node == null) {
            return;
        }
        if (list.size() == 0) {
            list.add(node);
            return;
        }
        int start = 0;
        int end = list.size() - 1;
        while (start <= end) {
            AppleNode startNode = list.get(start);
            AppleNode endNode = list.get(end);
            if (node.overdue > startNode.overdue) {
                list.add(start, node);
                return;
            }
            start++;
            if (node.overdue <= endNode.overdue) {
                list.add(end + 1, node);
                return;
            }
            end--;
        }
        list.add(start, node);
    }

    static class AppleNode {
        int index = 0;//date of manufacture
        int num = 0;//quantity
        int day = 0;//Shelf life days
        int overdue = 0;//expiration date 
    }

Topics: Algorithm leetcode regex