LeetCode Weekly Contest 112记录

本文代码全用C++实现哈。博主是C++小白,感觉自己很多地方代码不够简洁,欢迎大家批评指正。

945.使数组唯一的最小增量

给定整数数组 A,每次 move 操作将会选择任意 A[i],并将其递增 1。返回使 A 中的每个值都是唯一的最少操作次数。

思路

这道题比较简单,我做的时候并没有思考太多(以至于现在一下子不知道怎么讲思路)。要使每个值都唯一的话,先将数组进行排序(sort函数),然后逐个遍历,如果发现有A[i]<=A[i-1]的,就使move=move+A[i-1]+1-A[i],A[i]=A[i-1]+1。最后返回move。

代码

class Solution {
public:
    int minIncrementForUnique(vector<int>& A) {
        int move=0;
        int temp=0;
        int end=A.size();
        sort(A.begin(),A.end());
        int i=1;
        for(i=1;i<end;i++){
            if(A[i]<=A[i-1]){
                move+=A[i-1]+1-A[i];
                A[i]=A[i-1]+1;
            }
        }
        return move;
    }
};

946.验证栈序列

给定 pushed 和 popped 两个序列,只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时,返回 true;否则,返回 false 。
【示例】
输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1

思路

这题也比较简单,进行pop操作时,肯定是栈顶指针元素等于poped序列中最新一个待弹出的元素,我设置了i和j分别指向待入栈、待出栈元素,当二者相等时,i后退一位,j前进一位;当二者不相等时,i前进一位,j不动。具体实现过程中要仔细考虑各种临界情况。

代码

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
        int i=0,j=0;
        while(j<popped.size()&&i<pushed.size()){
            if(pushed[i]!=popped[j]){
                i++;
            }else{
                pushed.erase(pushed.begin()+i);
                j++;
                if(i>0)
                    i--;
            }
        }
        if(pushed.size()==0)
            return true;
        else
            return false;
    }
};

947.移除最多的同行或同列石头

在二维平面上,我们将石头放置在一些整数坐标点上。每个坐标点上最多只能有一块石头。
现在,move 操作将会移除与网格上的另一块石头共享一列或一行的石头。
我们最多能执行多少次 move 操作?

思路

哈,这道题是我写这篇博客的最大动力,先说解题思路。我们把处于同一行/同一列的石头视为连通,则每个连通向量都可以删到只剩下一个石头。我们只要从stones[0]出发找出连通向量S1,再从下一个未被访问过的点出发,找到连通向量S2……最后总石头数减去连通向量数(亦可看作保留的石子数),即可得到删掉的石头数目。
做题就是看了答案解析觉得so easy,但我当时自己做的时候并没有想到这样做,尝试了两三种很复杂的算法,搞了大半天。 (TAT)

代码

class Solution {
public:
    vector<int> path;//用于标记是否被访问过
    void initpath(vector<vector<int>>& stones){
        int i=0;
        while(i<stones.size()){
            path.push_back(0);
            i++;
        }
    }
    int find(vector<vector<int>>&stones,int begin){
        vector<int> footprint;
        footprint.push_back(begin);
        path[begin]=1;
        int fp=1,temp;
        while(footprint.size()>0){//遍历图,找出从这点出发的连通向量
            temp=footprint[footprint.size()-1];
            footprint.pop_back();
            for(int i=0;i<stones.size();i++){
                if(path[i]==0&&i!=temp){
                    if(stones[i][0]==stones[temp][0]||stones[i][1]==stones[temp][1]){
                        path[i]=1;
                        footprint.push_back(i);
                    }
                }
            }            
        }
        return 1;
    }
    int removeStones(vector<vector<int>>& stones) {
        initpath(stones);
        int i=0;int len=stones.size();
        int count=0;
        for(i=0;i<len;i++){
            if(path[i]==0){
                count+=find(stones,i);
            }
        }
        return stones.size()-count;
    }
};

948.令牌放置

你的初始能量为 P,初始分数为 0,只有一包令牌。
令牌的值为 token[i],每个令牌最多只能使用一次,可能的两种使用方法如下:
1.如果你至少有 token[i] 点能量,可以将令牌置为正面朝上,失去 token[i] 点能量,并得到 1 分。
2.如果我们至少有 1 分,可以将令牌置为反面朝上,获得 token[i] 点能量,并失去 1 分。
在使用任意数量的令牌后,返回我们可以得到的最大分数。

思路

既然要得到最多的分数,在舍弃分数获得能量的时候就要考虑舍弃1分能不能让自己获得更多?如果不行当然选择不换啦。因此我先将token数列进行排序(好用的sort),因为不管换多少能量都是扣一分,因此我们从数列末尾(end)开始进行分数换能量,从数列前端(begin)开始进行能量换分数。实现时要考虑详细各种情况下的选择策略,以及end和begin相遇时如何选择。

代码

class Solution {
public:
    int bagOfTokensScore(vector<int>& tokens, int P) {
        if(tokens.size()==0)
            return 0;
        sort(tokens.begin(),tokens.end());
        if(tokens[0]>P)
            return 0;
        int score=0;
        P-=tokens[0];score++;
        int end=tokens.size()-1;
        int begin=1;
        while(begin<=end){
            if(begin==end){
                if(P>=tokens[begin])
                    return score+1;
                else
                    return score;
            }
            else if(P<tokens[begin]&&score>=1){
                P+=tokens[end];
                score--;end--;
            }else if(P>=tokens[begin]){
                P-=tokens[begin];
                score++;begin++;
            }else if(P<tokens[begin]&&score<1){
                return score;
            }
        }
        return score;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值