0
点赞
收藏
分享

微信扫一扫

【LeetCode2434. medium】使用机器人打印字典序最小的字符串


​​2434. 使用机器人打印字典序最小的字符串​​

【LeetCode2434. medium】使用机器人打印字典序最小的字符串_c代码

 

【LeetCode2434. medium】使用机器人打印字典序最小的字符串_机器人_02

解题报告:

首先进行题意转换,其实上述两种操作描述的就是一个栈。

为什么要进行题意转换呢?因为你看题目说有两种操作,但是却不问最少的操作数,说明说不定这两种操作可以合并或者转换,与两种操作无关。

既然是字典序,考虑贪心。

本来想的是,从字符a-z进行遍历,先处理a在处理b这样,但是好像处理不了bdacb这种情况。

发现,最后的输出结果不一定是按照字母顺序来的。(即结果不是abdbc,而是abcdb)

然后发现没这么复杂,从栈的角度考虑贪心,啥时候入栈,啥时候输出,就行了。

AC代码:

class Solution:
def robotWithString(self, s: str) -> str:
dp = [0]*(len(s)+1)
dp[len(s)] = 'z'
dp[len(s)-1] = s[len(s)-1]
for i in range(len(s)-2,-1,-1):
dp[i] = dp[i+1]
if s[i] < dp[i]:
dp[i] = s[i]
i = 0
ans = ""
sk = []
while i < len(s):
sk.append(s[i])
while len(sk)>0 and sk[-1] <= dp[i+1]:
c = sk.pop()
ans = ans + c
i+=1
while len(sk) > 0:
ans = ans + sk.pop()

return ans

错误思路的代码:

假设当前处理的字符是c。

本来想着是,先往前看相邻的(输出,必须是连续的c字符),然后往后看(只输出c字符,一直到后面没有c字符),然后再往前看(栈内的全都输出,一直到输出完c字符)

几个地方要注意:

1、①那里,没必要,因为他可以和第二种方法合并,没必要先处理当前字符,然后再进流程。而且这些流程外的代码越多,需要加的特判也越多。(比如这里,需要判断pos<s.size(),也需要判断不想把当前值压入,而是直接处理栈内元素的情况)

2、写之前,想好是要每次操作完都pos++,还是下次操作前才pos++。

3、想好最外层for,是按照a~z的字符来,还是按照s这个串来。

4、有那些变量是要捆绑变化和维护的,要注意好。

5、vis和mp具体代表的含义到底是什么,要定义清楚,免得出现歧义。(其实vis虽然这么多地方维护,但是只使用了一次,在流程中的第二步使用到。所以在这之后其实就不需要维护vis了)

class Solution {
public:
string robotWithString(string s) {
string ans = "";
map<char, int> mp, vis;
for(auto c:s) {
mp[c] += 1;
}
string sk = "";
int pos = 0;
for(char c = 'a'; c<='z'; c++) {
if(mp[c] == 0) continue;

//1、没必要
// if(pos < s.size()) {
// sk.push_back(s[pos]);
// vis[s[pos]]++;
// pos++;
// }

int num = 0;
//先往前看
while(sk.size()>0&&sk.back() == c) {
ans.push_back(c);
sk.pop_back();
num++;
}
//再往后看
while(vis[c] < mp[c]) {
sk.push_back(s[pos]);
vis[s[pos]]++;
if(s[pos] == c) {
vis[c]++;
ans.push_back(c);
sk.pop_back();
num++;
}
pos++;
}
// 再往前看
while(num < mp[c] && sk.size()>0) {
char tmp = sk.back();sk.pop_back();
mp[tmp]--;vis[tmp]--;
ans.push_back(tmp);
}
}
return ans;
}
};

举报

相关推荐

0 条评论