LeetCode_Nov_2nd_Week
Posted KuoGavin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode_Nov_2nd_Week相关的知识,希望对你有一定的参考价值。
November 8th:299. 猜数字游戏
November 9th:488. 祖玛游戏
November 10th:495. 提莫攻击
November 8th : 299. 猜数字游戏
- ① 使用哈希表,总共进行了三次遍历,也即是第一次遍历密语,将所有的字符所对应的下标值给记录下来,第二次遍历进行对照,找出所有的公牛项,第三次遍历则是统计所有的奶牛项,这是最朴素的一种实现方式,当然时间和空间效率都不是特别理想;
- ② 将①中思想进行简化,使用数组充当哈希表,而且已知字符串中字符均为数字,则数组大小为 10 10 10,第一次遍历时将密语和猜测进行对照,若是相同则为公牛项,同时记录密语和猜测中各个数字字符出现的次数,第二次遍历则取哈希表中记录的密语和猜测的最小值,并进行累加则得到包括公牛项的奶牛项,最后返回公牛项数目和奶牛项数目(要减去公牛项数目)即可;
//version 1
class Solution {
public:
string getHint(string secret, string guess) {
int x = 0, y = 0;
typedef unordered_map<char, vector<int>> MCV;
MCV mcv;
vector<bool> marked(guess.size(), false);
for(int i = 0; i < secret.size(); ++i)
mcv[secret[i]].push_back(i);
for(int i = 0; i < guess.size(); ++i) {
if(mcv.find(guess[i]) != mcv.end()) {
auto iter = mcv[guess[i]].begin();
for(; iter != mcv[guess[i]].end(); ++iter) {
if(*iter == i) {
x++;
marked[i] = true;
mcv[guess[i]].erase(iter);
break;
}
}
}
}
for(int i = 0; i < guess.size(); ++i) {
if(marked[i]) continue;
if(mcv.find(guess[i]) != mcv.end() && mcv[guess[i]].size()) {
y++;
mcv[guess[i]].resize(mcv[guess[i]].size()-1);
}
}
return to_string(x) + "A" + to_string(y) + "B";
}
};
//version 2
class Solution {
public:
string getHint(string secret, string guess) {
vector<int> m_x = vector<int>(10);
vector<int> m_y = vector<int>(10);
int x = 0, y = 0;
for(int i = 0; i < secret.size(); ++i) {
m_x[secret[i] - '0']++;
m_y[guess[i] - '0']++;
if(secret[i] == guess[i]) x++;
}
for(int i = 0; i < 10; ++i) y += min(m_x[i], m_y[i]);
return to_string(x) + "A" + to_string(y - x) + "B";
}
};
November 9th : 488. 祖玛游戏
一个暴力的dfs穷举题目,题解如下:
class Solution {
public:
int min_cnt = 0x3f3f3f3f; //最终返回的需要球的最小个数,0x3f的问题,主要是memset按字节进行填充,可见我博客
//unordered_set对pair没有hash方式,所以使用set,否则编译时报错
set<pair<string, int>> vis; //记录是否已经处理过相同的子问题,以用于剪枝,记忆化递归
void processBoard(string& board) { //处理字符串,找出整个字符串中长度大于等于3的字符串,并删除
for (int slow = 0,fast = 0; fast <= board.size(); fast++) {
if (fast < board.size() && board[slow] == board[fast]) continue; //相同快指针继续右移
if (fast - slow >= 3) { //当前快慢指针所圈定的窗口大小大于等于3则进行字符串的裁剪
board.erase(slow, fast - slow);
fast = 0; //重新从头开始对字符串进行裁剪
}
slow = fast; //此时slow和fast指向的字符不同,进行调整
}
}
//深搜函数
void helper(string& board, string& hand, int cnt) {
if (cnt >= min_cnt) return; //如果当前所用球数已经大于之前记录的最小,则剪枝
if (vis.count({board, cnt})) return; //如果当前情形,之前已经出现过,则剪枝
vis.insert({board, cnt}); //作为一种新的情况进行处理
if (board.empty()) { //如果board空了,则说明祖玛珠子消完了,则进行结果更新
min_cnt = min(min_cnt, cnt);
return;
}
if (hand.empty()) return; //没有珠子了,无法进行消除操作,返回
int n = board.size(), m = hand.size();
for (int i = 0; i < n; ++i) { //将每个hand中的珠子放置到board当中的任意位置,进行穷举
for (int j = 0; j < m; ++j) {
char ch = hand[j];
hand.erase(hand.begin() + j); //从hand中除去该次取用的祖玛珠子
//new board
string nb = board; //得到board的一个副本
nb.insert(nb.begin() + i, ch); //在i位置加上所取用的祖玛珠子
processBoard(nb); //对新得到的祖玛珠子序列进行处理、裁剪
helper(nb, hand, cnt + 1); //进行递归调用,对新的珠子序列和备选珠子,还有所用珠子数目
hand.insert(hand.begin() + j, ch); //恢复hand,加上该次所取用的祖玛珠子
}
}
}
int findMinStep(string board, string hand) {
helper(board, hand, 0);
return min_cnt == 0x3f3f3f3f ? -1 : min_cnt; //如果为0x3f3f3f3f,则说明没法完全消除
}
};
November 10th : 495. 提莫攻击
合着这道题是应景 EDG S11夺冠 的是吗?其实题目本身很简单,抽象出来就是求区间的不重复长度,即是第
i
−
1
i-1
i−1 次中毒的结束时间fin[i-1] = timeSeries[i-1]+duration>timeSeries[i] ? timeSeries[i-1]+duration : timeSeries[i]
,然后对中毒时间进行累加即可,ret += dp[i-1]-timeSeries[i-1]
,最后一次中毒一定拉满一个
d
u
r
a
t
i
o
n
duration
duration 时间,加上就可以得到结果。
//version 1 按照上面思路的代码
class Solution {
public:
int findPoisonedDuration(vector<int>& timeSeries, int duration) {
int ret = 0, dp0;
for(int i = 1; i < timeSeries.size(); ++i) {
ret += (timeSeries[i]-duration>timeSeries[i-1] ?
timeSeries[i-1] + duration : timeSeries[i]) -
timeSeries[i-1];
}
return ret + duration;
}
};
//version 2 将上面思路做了拆解,也即是三目运算换成了if-else分支
class Solution {
public:
int findPoisonedDuration(vector<int>& timeSeries, int duration) {
int ret = 0;
for(int i = 1; i < timeSeries.size(); ++i) {
if(timeSeries[i-1] + duration <= timeSeries[i]) ret += duration;
else ret += timeSeries[i] - timeSeries[i-1];
}
return ret + duration;
}
};
以上是关于LeetCode_Nov_2nd_Week的主要内容,如果未能解决你的问题,请参考以下文章