文章链接: 134. 加油站 135. 分发糖果 860.柠檬水找零 406.根据身高重建队列

视频链接: 134. 加油站 135. 分发糖果 860.柠檬水找零 406.根据身高重建队列

题目链接: 134. 加油站 135. 分发糖果 860.柠檬水找零 406.根据身高重建队列


134.加油站

思路:

局部最优:到一个加油站 存的油 要比去下一个站点所 消耗的油 多(或等于);

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int curSum = 0;
        int tolSum = 0;
        int start = 0;
        for(int i = 0; i < gas.size(); i++) {
            curSum += gas[i] - cost[i]; // 去下一个站点所剩的油
            tolSum += gas[i] - cost[i];
            if(curSum < 0) { // 表示前面的所有站点都不可以作为起点(可用反证法得知)
                curSum = 0;
                start = i + 1; // 更新起点
            }
        }
        if(tolSum < 0) return -1; // 永远走不到
        return start;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.


135.分发糖果

思路:

重要思想处理好一边再处理另一边,不要两边想着一起兼顾。

1.先从前往后,将要确定糖果数目的孩子与他的左边比较;

2.再从后往前,将要确定糖果数目的孩子与他的右边比较;

class Solution {
public:
    int candy(vector<int>& ratings) {
        vector<int> candyVec(ratings.size(), 1);

        // 从前往后(与左边的相比)
        for(int i = 1; i < ratings.size(); i++) {
            if(ratings[i] > ratings[i - 1]) {
                candyVec[i] = candyVec[i - 1] + 1;
            }
        }

        // 从后往左(与右边的相比)
        for(int i = ratings.size() - 2; i >= 0; i--) {
            if(ratings[i] > ratings[i + 1]) {
                candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1);
            }
        }

        int result = 0;
        for(int i : candyVec) {
            result += i;
        }
        return result;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.

860.柠檬水找零

思路:

分为三种情况:

1.顾客支付5元:直接收;

2.顾客支付10元:返回顾客一张5元;

3.顾客支付20元:返回顾客三张5元;或者返回顾客一张10元和一张5元;

class Solution {
public:
    bool lemonadeChange(vector<int>& bills) {
        int five = 0, ten = 0, twenty = 0;
        for (int i : bills) {
            // 第一种情况:
            if (i == 5) {
                five++;
            }

            // 第二种情况:
            if (i == 10) {
                if (five == 0)
                    return false;
                ten++;
                five--;
            }

            // 第三种情况:
            if (i == 20) {
                if (five > 0 && ten > 0) {
                    five--;
                    ten--;
                } else if (five >= 3) {
                    five -= 3;
                } else {
                    return false;
                }
            }
        }
        return true;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.


406.根据身高重建队列

思路:

重要思想处理好一边再处理另一边,不要两边想着一起兼顾。

1.先将身高从大到小排;

2.根据k的大小调整位置。

// 用链表实现,比vector快
class Solution {
public:
    static bool cmp(const vector<int>& a, const vector<int>& b) {
        if(a[0] == b[0]) return a[1] < b[1];
        return a[0] > b[0];
    }

    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(), people.end(), cmp);
        list<vector<int>> que; // 链表
        for(int i = 0; i < people.size(); i++) {
            int position = people[i][1]; // 表示要插入的下标为position的位置
            std::list<vector<int>>::iterator it = que.begin();
            while(position--) { // 寻找插入的位置
                it++;
            }
            que.insert(it, people[i]);
        }
        return vector<vector<int>>(que.begin(), que.end()); // 返回整个队列
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

补充:

static用法: C/C++ 中 static 的用法全局变量与局部变量 | 菜鸟教程 (runoob.com)

简单理解:静态全局变量