# 程序员进阶之算法练习（三十三）LeetCode专场

BAT常见的算法面试题解析：

### 正文

#### 1、Binary Tree Right Side View

``````
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
vector<int> ret;
if (root) {
dfs(root, ret, 0);
}
return ret;
}

void dfs(TreeNode* root, vector<int> &ret, int dep) {
if (ret.size() <= dep) {
ret.push_back(root->val);
}
if (root->right) {
dfs(root->right, ret, dep + 1);
}
if (root->left) {
dfs(root->left, ret, dep + 1);
}
}
};
``````

#### 2、Valid Parentheses

1、所有括号都是匹配的；（左右括号数量一致）
2、匹配的括号是合法的；（没有交错）

Example 1:
Input: "()"
Output: true

Example 2:
Input: "()[]{}"
Output: true

Example 3:
Input: "(]"
Output: false

Example 4:
Input: "([)]"
Output: false

Example 5:
Input: "{[]}"
Output: true

1、遇到一个字符，先看栈是否为空，如果为空则直接入栈；如果栈不为空，则看当前字符是左括号还是右括号；
2、如果是左括号，直接入栈；
3、如果是右括号，则看栈顶元素是否为左括号，并且匹配；
4、最后看栈是否为空。

``````
class Solution {
public:
bool isValid(string s) {
stack<char> stk;
for (int i = 0; i < s.length(); ++i) {
int c = s[i];
if (stk.size() == 0) {
stk.push(c);
}
else {
if (c == '[' || c == '{' || c == '(') {
stk.push(c);
}
else {
char top = stk.top();
stk.pop();
if ((c == ']' && top != '[') || (c == '}' && top != '{') || (c == ')' && top != '(')) {
return false;
}
}
}
}
return stk.size() == 0;
}
}leetcode;

``````

#### 3、Letter Combinations of a Phone Number

Example:
Input: "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

``````

class Solution {
public:

void dfs(string &digits, int i, string &tmp, vector<string> &ret) {
if (i >= digits.length()) {
ret.push_back(tmp);
return;
}
else {
int nums[10] =
{
0,
0, 3, 3,
3, 3, 3,
4, 3, 4,
};

int index = digits[i] - '0';
int start = 0;
for (int i = 2; i < index; ++i) {
start += nums[i];
}
int end = start + nums[index];
for (int j = start; j < end; ++j) {
tmp.push_back('a' + j);
dfs(digits, i + 1, tmp, ret);
tmp.pop_back();
}
}
}

vector<string> letterCombinations(string digits) {
vector<string> ret;
string tmp;
if (digits.length()) {
dfs(digits, 0, tmp, ret);
}
return ret;
}
}leetcode;

``````

#### 4、Shortest Palindrome

``````class Solution {
public:
string shortestPalindrome(string s) {
vector<char> str(s.length() * 2 + 5);
vector<int> p(str.size());
str[0] = '@';
int i, j;
for(i = 0, j = 1; s[i]; i++){
str[j++] = '#';
str[j++] = s[i];
}
str[j++] = '#';
int n = j;
manachar(str, p, n);
int ans = 0, pos = 0;
for(i = 1; i < n; i++) { // @#a#b#a#a#
if (p[i] == i) { // 能覆盖到最左边
pos = i;
ans = p[i] - 1; // 回文串长度
}
}
string add = string(s.begin() + ans, s.end());
}

void manachar(vector<char> &str, vector<int> &p, int n){
int id = 0, mx = 0;
for(int i = 1; i < n; i++){
if(mx > i) p[i] = min(p[2 * id - i], mx - i);
else p[i] = 1;
while(str[i + p[i]] == str[i - p[i]]) p[i]++;
if(p[i] + i > mx) mx = p[i] + i, id = i;
}
}
}leetcode;
``````

#### 5、Dungeon Game

n*m的网格，每个网格有一个数字，要从左上角到右下角（只能向右或者向左）；

``````    int calculateMinimumHP(vector<vector<int>>& dungeon) {
int left = 1, right = inf, ans = 0;
while (left <= right) {
int mid = (left + right) / 2;
if (canPass(dungeon, mid)) {
ans = mid;
right = mid - 1;
}
else {
left = mid + 1;
}
}
return ans;
}
``````

canPass的思路就是：在n*m的网格中，遍历所有能到达的点，看是否能到达右下角；

1、如果想到合适的解法；
2、把解法用合适的代码表达出来；

algorithm