本文代码全用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;
}
};