码随想录算法训练营第二十九天|加油站、分发糖果、柠檬水找零、根据身高重建队列

加油站 leetcode 134

解法一:暴力解法for循环嵌套while循环

for循环适合模拟从头到尾的遍历,而while循环适合模拟环形遍历

index=(i+1)%gas,size();模拟一个新的索引确保其在gas数组大小范围内。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        for(int i=0;i<gas.size();i++){
            int rest=gas[i]-cost[i];
            int index=(i+1)%gas.size();
            while(rest>0&&index!=i){
                rest+=gas[index]-cost[index];
                index=(index+1)%gas.size();
            }
            if(rest>=0&&index==i) return i;
        }
        return -1;
    }
};

解法二:贪心算法

算出到达每一站的剩余油量,for循环遍历每个站点,一旦到达当前站点剩余油量小于0则记录起始位置为i+1,并清空剩余油量继续遍历。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int curSum=0,tatalSum=0,start=0;
        for(int i=0;i<gas.size();i++){
            curSum+=gas[i]-cost[i];
            tatalSum+=gas[i]-cost[i];
            if(curSum<0){
                start=i+1;
                curSum=0;
            }
        }
        if(tatalSum<0) return -1;
        return start;
    }
};

分发糖果 leetcode 135

第一种情况,右边孩子评分大于左边孩子,从前向后遍历,然后考虑左边孩子评分大于右边孩子的情况,从后向前遍历,取两次情况分发糖果的最大值。

class Solution {
public:
    int candy(vector<int>& ratings) {
        vector<int> candY(ratings.size(),1);
        for(int i=1;i<ratings.size();i++){
            if(ratings[i]>ratings[i-1]) candY[i]=candY[i-1]+1;
        }
        for(int i=ratings.size()-2;i>=0;i--){
            if(ratings[i]>ratings[i+1]) candY[i]=max(candY[i+1]+1,candY[i]);
        }
        int sum=0;
        for(int i=0;i<candY.size();i++){
            sum+=candY[i];
        }
        return sum;
    }
};

总结

有两边一起比较的题目,先确定一边再确定另一边!

柠檬水找零 leetcode 860

一共三种情况,收到5、10、20分别记录(20不用记录因为不会用来找零)。收到20优先使用10找零,没有10再用三张5。

class Solution {
public:
    bool lemonadeChange(vector<int>& bills) {
        int five=0,ten=0;
        for(int i=0;i<bills.size();i++){
            if(bills[i]==5) five++;
            if(bills[i]==10){
                ten++;
                five--;
                if(five<0) return false;
            }
            if(bills[i]==20){
                if(five>0&&ten>0){
                    five--;
                    ten--;
                }else if(five>=3){
                    five-=3;
                }else return false;
            }
        }
        return true;
    }
};

根据身高重建队列 leetcode 406

先根据身高从大到小排序(如果身高大小相同就按前面有几个人比自身高的数量从小到大排序),再根据前面有几个人比自身高就插入到队列对应索引位置。

解法一:使用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);
        vector<vector<int>> queue;
        for(int i=0;i<people.size();i++){
            int position=people[i][1];
            people.insert(people.begin()+position,people[i]);
        } 
        return queue;
    }
};

C++中vector(可以理解是一个动态数组,底层是普通数组实现的)如果插入元素大于预先普通数组大小,vector底部会有一个扩容的操作,即申请两倍于原先普通数组的大小,然后把数据拷贝到另一个更大的数组上。

所以使用vector(动态数组)来insert,是费时的,插入再拷贝的话,单纯一个插入的操作就是O(n^2)了,甚至可能拷贝好几次,就不止O(n^2)了。

解法二:使用list(其底层为链表)

lass 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) {
        list<vector<int>> que;
        sort(people.begin(),people.end(),cmp);
        for(int i=0;i<people.size();i++){
            int position=people[i][1];
            list<vector<int>>::iterator it=que.begin(); 
            //auto it=que.begin();
            while(position--){
                it++;
            }
            que.insert(it,people[i]);
        }
        return vector<vector<int>>(que.begin(),que.end());
    }
};
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法。 总之,代随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值