Monthly Archives: March 2017

LeetCode Kth Smallest Element in a BST

230. Kth Smallest Element in a BST

Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.

Example 1:

Input: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
Output: 1

Example 2:

Input: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
Output: 3

Follow up:
What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine?

Constraints:

  • The number of elements of the BST is between 1 to 10^4.
  • You may assume k is always valid, 1 ≤ k ≤ BST's total elements.

给定一棵二叉搜索树,问树中第k小的元素是哪个。 因为BST的特点是左<=根<=右,所以对树中序遍历之后就得到升序序列,取出第k个元素即可。代码如下:

class Solution {
private:
    void inOrder(TreeNode* root, int& k, int& target)
    {
        if (k < 0)
            return;
        if (root->left)
            inOrder(root->left, k, target);
        –k;
        if (k == 0)
            target = root->val;
        if (root->right)
            inOrder(root->right, k, target);
    }
public:
    int kthSmallest(TreeNode* root, int k)
    {
        int target;
        inOrder(root, k, target);
        return target;
    }
};

本代码提交AC,用时26MS,时间复杂度是O(k)。
Follow up指出如果可以修改节点,怎样才能使得复杂度降低到O(height of tree),可以给每个节点增加一个属性rank:左子树节点个数,该属性的含义就是小于该节点的节点个数,也即当前节点在中序遍历中的位置(rank)。查找的过程就类似二分了,从根节点开始,如果k小于当前节点的rank,说明第k小的数在左子树;如果k大于当前节点的rank,说明第k小的数在右子树;如果k==rank,则当前节点就是第k小的数。这样的查找过程就是不断的在当前节点选择走左子树还是右子树,走过的节点最多是树的高度。
rank属性可以在建BST时完成。

hihoCoder 1487-岛屿3

hihoCoder 1487-岛屿3

#1487 : 岛屿3

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

H国正在进行一项持续N周的填海造岛工程。整片工程海域可以被看作是1000×1000的网格。 每周都有一块1×1的单位方格海域被填成陆地。如果我们将连成一片的陆地(一块单位方格与它上下左右4个单位方格是相连的)视为岛屿,H国想监测每周末整片海域中一共存在有多少个岛屿,以及这些岛屿的总面积和总周长各是多少。 假设工程持续三周,第一周被填的海域坐标是(0, 0),那么第一周结束后有1座岛屿、总面积是1、总周长是4:
#..
...
...
第二周被填的海域坐标是(1, 1),那么第二周结束后有2座岛屿、总面积是2、总周长是8:
#..
.#.
...
第三周被填的海域坐标是(1, 0),那么第三周结束后有1座岛屿、总面积是3、总周长是8:
#..
##.
...
你能完成这项任务么?

输入

第一行包含一个整数N,表示工程持续的周数。(1 <= N <= 100000) 以下N行每行包含两个整数x和y,表示当周被填的海域坐标。(0 <= x, y < 1000)

输出

输出N行,每行包含3个整数,依次是当周末岛屿的数量、总面积和总周长。
样例输入
3
0 0
1 1
1 0
样例输出
1 1 4
2 2 8
1 3 8

有一个1000*1000的海域,每周往其中填入1*1的陆地,要求输出每周该海域中会形成多少个岛屿,以及岛屿的总面积和总周长。 其实这题不算难,只是太久没用并查集,用了DFS导致超时了。现在分别介绍两种方法。 首先我们来解决总面积和总周长这两个问题。 总面积好说,每周填入一个单元的陆地,则面积加一。 总周长要稍微注意,如果新加入的方块和其他所有方块都不邻接,则贡献+4周长;如果和一个已有方块邻接,则贡献+4-2周长;如果和两个已有方块邻接,则贡献+4-2*2周长;如果和3个已有方块邻接,则贡献+4-2*3周长。。。所以每加入一个方块,就看看该方块四周,如果和intercnt个方块邻接,则贡献周长+4-2*intercnt。 最麻烦的是求岛屿个数。当然可以像往常一样,对所有点DFS,求连通分量,但是TLE。 我稍微优化了一下,在board中,把每个连通分量都标记为一个不同的islandID,每次新加入一个方块时,令board[x][y]=++islandID,并从这个方块开始DFS,把所有和(x,y)连通的方块的ID都标记为新的(x,y)的islandID,同时记录一下被(x,y) DFS的方块旧的islandID。通过这个过程,能知道新方块(x,y)和多少个不同的旧岛屿相连,同时把所有和(x,y)相连的旧岛屿都标记为新的islandID了。 假设原来有n个岛屿,和新方块相连的旧岛屿有m个,则加入新方块之后,岛屿数更新为n-m+1,即m个旧岛屿都缩成1个新岛屿了。 DFS思路的代码如下: [cpp] #include<iostream> #include<vector> #include<algorithm> #include<utility> #include<cstdio> #include<unordered_set> using namespace std; vector<vector<int>> board(1000, vector<int>(1000, 0)); vector<pair<int,int>> dirs = { {1,0},{-1,0},{0,1},{0,-1} }; void dfs(int x,int y, int islandID, unordered_set<int>& neighbor) { neighbor.insert(board[x][y]); board[x][y] = islandID; for (int i = 0; i < dirs.size(); ++i) { int newx = x + dirs[i].first, newy = y + dirs[i].second; if (newx >= 0 && newx < 1000 && newy >= 0 && newy < 1000 && board[newx][newy] != 0 && board[newx][newy] != islandID)dfs(newx, newy, islandID, neighbor); } } int main() { //freopen("input.txt", "r", stdin); int N, x, y; int island = 0, area = 0, perimeter = 0; int islandID = 1; bool first = true; scanf("%d", &N); while (N–) { scanf("%d %d", &x, &y); board[x][y] = islandID; ++area; if (first) { perimeter = 4; island = 1; first = false; } else { int intercnt = 0; // 邻接方块数 for (int i = 0; i < dirs.size(); ++i) { int newx = x + dirs[i].first, newy = y + dirs[i].second; if (newx >= 0 && newx < 1000 && newy >= 0 && newy < 1000 && board[newx][newy] != 0)++intercnt; } perimeter = perimeter + 4 – 2 * intercnt; if (intercnt == 0)++island; else { unordered_set<int> neighbor; // 邻接岛屿旧编号+新方块编号 dfs(x, y, islandID, neighbor); island = island – neighbor.size() + 2; // 因为neighbor中包含新方块编号,所以这里要多加1 } } ++islandID; printf("%d %d %d\n", island, area, perimeter); } return 0; } [/cpp] 本代码提交TLE,用时2792MS。 比赛结束之后,看了看AC的代码,用的全是并查集,没一个用DFS的。。。 好吧,那就改成并查集。求总面积和总周长的方法都一样,不同的是求岛屿个数。 我们用数组来实现并查集,把坐标(x,y)编码成x*1000+y便于存入一维数组。对于每个新加入的点u,在并查集中先用自己代表自己,represent[u]=u。然后环顾四周,把四周陆地所在岛屿的代表放到neighbor中并去重,这样就能得到新方块邻接的旧岛屿数,根据n-m+1算到新岛屿数。最后把邻接的旧岛屿和新方块u union起来。 代码如下: [cpp] #include<iostream> #include<vector> #include<algorithm> #include<utility> #include<cstdio> #include<unordered_set> using namespace std; vector<vector<int>> board(1000, vector<int>(1000, 0)); vector<pair<int, int>> dirs = { { 1,0 },{ -1,0 },{ 0,1 },{ 0,-1 } }; vector<int> represent(1000 * 1000, -1); int find_rep(int u) { if (u == represent[u])return u; else { represent[u] = find_rep(represent[u]); return represent[u]; } } void union_rep(int u, int v) { represent[find_rep(u)] = find_rep(v); } int main() { //freopen("input.txt", "r", stdin); int N, x, y, u; int island = 0, area = 0, perimeter = 0; bool first = true; scanf("%d", &N); while (N–) { scanf("%d %d", &x, &y); board[x][y] = 1; ++area; u = x * 1000 + y; represent[u] = u; if (first) { perimeter = 4; island = 1; first = false; } else { int intercnt = 0; // 邻接方块数 unordered_set<int> neighbor; // 邻接岛屿 for (int i = 0; i < dirs.size(); ++i) { int newx = x + dirs[i].first, newy = y + dirs[i].second; if (newx >= 0 && newx < 1000 && newy >= 0 && newy < 1000 && board[newx][newy] == 1) { ++intercnt; neighbor.insert(find_rep(newx * 1000 + newy)); } } for (auto it = neighbor.begin(); it != neighbor.end(); ++it)union_rep(u, *it); perimeter = perimeter + 4 – 2 * intercnt; island = island – neighbor.size() + 1; } printf("%d %d %d\n", island, area, perimeter); } return 0; } [/cpp] 本代码提交AC,用时436MS,果然快了不少。]]>

hihoCoder 1485-hiho字符串

hihoCoder 1485-hiho字符串

#1485 : hiho字符串

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

如果一个字符串恰好包含2个’h’、1个’i’和1个’o’,我们就称这个字符串是hiho字符串。 例如”oihateher”、”hugeinputhugeoutput”都是hiho字符串。 现在给定一个只包含小写字母的字符串S,小Hi想知道S的所有子串中,最短的hiho字符串是哪个。

输入

字符串S 对于80%的数据,S的长度不超过1000 对于100%的数据,S的长度不超过100000

输出

找到S的所有子串中,最短的hiho字符串是哪个,输出该子串的长度。如果S的子串中没有hiho字符串,输出-1。
样例输入
happyhahaiohell
样例输出
5

如果字符串中包含2个h,1个i和1个o,则称该子串为hiho字符串。给定一个字符串s,问s中最短的hiho子串长度是多少。如果不存在hiho子串,则输出-1。 首先,肯定不能用两层循环暴力解法,这样的话需要$$O(n^3)$$,因为判断子串是否是hiho串还需要O(n),所以乘起来就是$$O(n^3)$$。 我当时的解法是,首先扫一遍字符串,记录下每个位置及其前面出现的h,i,o字符总数。然后我使用两层循环,把对应位置的h,i,o数目作差,如果等于2,1,1,则更新结果。但是$$O(n^2)$$的复杂度还是TLE了。 看了下第一名的解法,虽然复杂度也是$$O(n^2)$$,但是高明许多。设置两个指针i,j,区间[i,j]相当于一个滑动窗口,对于每个i,j往后走,直到h,i,o次数不低于2,1,1,如果正好是2,1,1,则把当前长度j-i和结果比较。i往后走时,对应的s[i]频率要减1。 代码如下,注意第23行,必须是大于号,不能是大于等于,因为如果只是hash[‘o’]==1就跳出的话,假设输入字符串是”oihateher”,则第0位时hash[‘o’]==1,此时跳出,导致起点i变成了1而找不到正确结果。具体用这个样例测试一下就知道。 [cpp] #include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; const int MAXN = 100005; int main() { string s; cin >> s; //s = "oihateher"; int n = s.size(); if (n < 4) { cout << -1; return 0; } vector<int> hash(256, 0); int ans = MAXN; for (int i = 0, j = 0; i < n; ++i) { while (j < n && (hash[‘h’] < 2 || hash[‘i’] < 1 || hash[‘o’] < 1)) { ++hash[s[j++]]; if (hash[‘h’] > 2 || hash[‘i’] > 1 || hash[‘o’] > 1)break; } if (hash[‘h’] == 2 && hash[‘i’] == 1 && hash[‘o’] == 1) ans = min(ans, j – i); –hash[s[i]]; } if (ans == MAXN)cout << -1; else cout << ans; return 0; } [/cpp] 本代码提交AC,用时13MS。]]>

LeetCode Is Subsequence

LeetCode Is Subsequence Given a string s and a string t, check if s is subsequence of t. You may assume that there is only lower case English letters in both s and t. t is potentially a very long (length ~= 500,000) string, and s is a short string (<=100). A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ace" is a subsequence of "abcde" while "aec" is not). Example 1: s = "abc", t = "ahbgdc" Return true. Example 2: s = "axc", t = "ahbgdc" Return false. Follow up: If there are lots of incoming S, say S1, S2, … , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?


给定两个字符串s和t,判断s是否是t的子序列。子序列的概念和子串不一样,如果s是t的子串,则s必须是t中连续的一段;而如果是子序列的话,则s只需要是t中若干个字符,但这些字符顺序必须和t中的一样。 比如t=”abcdefghijk”,则”cdef”既可以是t的子串,也可以是t的子序列;而”bfjk”只能是t的子序列。 本题很简单,维护两个指针i,j,分别指向s和t,从t中不断找字符s[i],没找到只递增j,找到的话同时递增i和j。如果最后i到达s的末尾了,说明s是t的子序列,否则不是。 代码如下: [cpp] class Solution { public: bool isSubsequence(string s, string t) { int m = s.size(), n = t.size(); if (m > n)return false; int i = 0, j = 0; while (i < m&&j < n) { while (j < n&&s[i] != t[j])++j; if (j >= n)return false; ++i; ++j; } return i == m; } }; [/cpp] 本代码提交AC,用时73MS。]]>

LeetCode Minimum Time Difference

LeetCode Minimum Time Difference Given a list of 24-hour clock time points in “Hour:Minutes” format, find the minimum minutes difference between any two time points in the list. Example 1:

Input: ["23:59","00:00"]
Output: 1
Note:
  1. The number of time points in the given list is at least 2 and won’t exceed 20000.
  2. The input time is legal and ranges from 00:00 to 23:59.

给定一个时间字符串数组,问数组中任意两个时间之差最小是多少分钟。 本题的基本思路是把数组中所有的时间表示转换为分钟,然后排序求相邻两个分钟之间的最小差。 本题的一个小难点是时间是循环的,比如01:30和06:30差5小时,但01:30和23:30差几小时呢?如果顺着看差22小时,好像比前一个差要大,但是逆着看,实际上只差2小时。所以分立0点两边的两个时间差其实有两个。处理办法是把0~12点之间的时间转换为两个分钟数,一个是0~12以内的,另一个是12~24以内的。 代码如下: [cpp] class Solution { private: void convertToMinutes(const string& s, vector<int>& minutes) { int pos = s.find(‘:’); int hour = atoi(s.substr(0, pos).c_str()), minute = atoi(s.substr(pos + 1).c_str()); int m = hour * 60 + minute; minutes.push_back(m); if (hour < 12)minutes.push_back(m + 24 * 60); } public: int findMinDifference(vector<string>& timePoints) { vector<int> minutes; for (int i = 0; i < timePoints.size(); ++i) { convertToMinutes(timePoints[i], minutes); } sort(minutes.begin(), minutes.end()); int ans = INT_MAX; for (int i = 1; i < minutes.size(); ++i) { ans = min(ans, minutes[i] – minutes[i – 1]); } return ans; } }; [/cpp] 本代码提交AC,用时19MS。]]>

LeetCode Count Numbers with Unique Digits

LeetCode Count Numbers with Unique Digits Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n. Example: Given n = 2, return 91. (The answer should be the total numbers in the range of 0 ≤ x < 100, excluding [11,22,33,44,55,66,77,88,99]) Hint:

  1. A direct way is to use the backtracking approach.
  2. Backtracking should contains three states which are (the current number, number of steps to get that number and a bitmask which represent which number is marked as visited so far in the current number). Start with state (0,0,0) and count all valid number till we reach number of steps equals to 10n.
  3. This problem can also be solved using a dynamic programming approach and some knowledge of combinatorics.
  4. Let f(k) = count of numbers with unique digits with length equals k.
  5. f(1) = 10, …, f(k) = 9 * 9 * 8 * … (9 – k + 2) [The first factor is 9 because a number cannot start with 0].

给定n,问在[0,10n)内有多少个每一位都是不同数字的数。比如当n=2时,在[0,100)内,有91个这样的数,需要排除个位和十位数字相同的9个数。 其实这个题很简单,假设k表示数的位数,找一下规律:
  • k=1,一位数,可以填入0~9这10个数,结果为10
  • k=2,两位数,十位填入1~9这9个数,个位填入0~9中除了十位的那个数字,有9种情况,结果为9*9
  • k=3,三位数,百位填入1~9这9个数字,十位填入0~9中除了百位的那个数字,有9种情况,个位填入0~9中除了百位和十位的那两个数字,有8种情况,结果为9*9*8
  • k=n,结果为9*9*8*…*(9-n+2)
所以我们可以用DP解题,f(k)=f(k-1)*(9-k+2),为了节省空间,只需保存上一次的结果f(k-1)。在DP的过程中,累加f(k)的结果。 代码如下: [cpp] class Solution { public: int countNumbersWithUniqueDigits(int n) { if (n == 0)return 1; if (n == 1)return 10; int ans = 10, last = 9; for (int i = 2; i <= n; ++i) { last *= (9 – i + 2); ans += last; } return ans; } }; [/cpp] 本代码提交AC,用时3MS。]]>

LeetCode Diagonal Traverse

LeetCode Diagonal Traverse Given a matrix of M x N elements (M rows, N columns), return all elements of the matrix in diagonal order as shown in the below image. Example:

Input:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
Output:  [1,2,4,7,5,3,6,8,9]
Explanation:

Note:
  1. The total number of elements of the given matrix will not exceed 10,000.

给定一个矩阵,要求以对角线的方式遍历该矩阵。 没什么特别的技巧,模拟对角线走法即可。设置一个up变量,设置up=true表示向右上角走,i–,j++;up=false表示向左下角走,i++,j–。 边界情况处理有点复杂。当向右上角走时,有两种情况,如果越过了右边界,比如样例中3往右上角走了一步,则要回到6的位置,方法是i+=2,j=n-1;如果没有越过右边界,只是越过了上边界,比如图中的1再往右上角走了一步,则只需要i=0。注意这两种判断的顺序不能乱,必须先判断是否越过了右边界,再判断是否越过了上边界。 当往左下角走时,越界处理的方法类似。如果越过了下边界,比如8再往左下角走了一步,则需要i=m-1,j+=2;如果只越过了左边界,比如4再往左下角走了一步,则只需要j=0。 完整代码如下: [cpp] class Solution { public: vector<int> findDiagonalOrder(vector<vector<int>>& matrix) { int m = matrix.size(), n = 0; if (m != 0)n = matrix[0].size(); if (m == 0 || n == 0)return vector<int>(); vector<int> ans; int i = 0, j = 0; bool up = true; while (!(i == m – 1 && j == n – 1)) { ans.push_back(matrix[i][j]); if (up) { –i; ++j; if (j >= n) { i += 2; j = n – 1; up = false; } if (i < 0) { i = 0; up = false; } } else { ++i; –j; if (i >= m) { i = m – 1; j += 2; up = true; } if (j < 0) { j = 0; up = true; } } } ans.push_back(matrix[m – 1][n – 1]); return ans; } }; [/cpp] 本代码提交AC,用时86MS。]]>

LeetCode Most Frequent Subtree Sum

LeetCode Most Frequent Subtree Sum Given the root of a tree, you are asked to find the most frequent subtree sum. The subtree sum of a node is defined as the sum of all the node values formed by the subtree rooted at that node (including the node itself). So what is the most frequent subtree sum value? If there is a tie, return all the values with the highest frequency in any order. Examples 1 Input:

  5
 /  \
2   -3
return [2, -3, 4], since all the values happen only once, return all of them in any order. Examples 2 Input:
  5
 /  \
2   -5
return [2], since 2 happens twice, however -5 only occur once. Note: You may assume the sum of values in any subtree is in the range of 32-bit signed integer.
给定一棵二叉树,问频率最大的子树之和是哪个数。子树之和是指根节点及其子节点的和。 简单题,使用后序遍历把所有子树之和统计一遍,用Hash记录和与频率的关系,然后找出最大频率的和。 代码如下: [cpp] class Solution { private: int postOrder(TreeNode* root, unordered_map<int, int>& hash) { int sum = 0; if (root->left)sum += postOrder(root->left, hash); if (root->right)sum += postOrder(root->right, hash); sum += root->val; ++hash[sum]; return sum; } public: vector<int> findFrequentTreeSum(TreeNode* root) { if (!root)return vector<int>(); unordered_map<int, int> hash; postOrder(root, hash); int maxCnt = 0; for (auto it = hash.begin(); it != hash.end(); ++it)maxCnt = max(maxCnt, (*it).second); vector<int> ans; for (auto it = hash.begin(); it != hash.end(); ++it) { if ((*it).second == maxCnt)ans.push_back((*it).first); } return ans; } }; [/cpp] 本代码提交AC,用时19MS。]]>

LeetCode Minesweeper

LeetCode Minesweeper Let’s play the minesweeper game (Wikipedia, online game)! You are given a 2D char matrix representing the game board. ‘M’ represents an unrevealed mine, ‘E’ represents an unrevealed empty square, ‘B’ represents a revealed blank square that has no adjacent (above, below, left, right, and all 4 diagonals) mines, digit (‘1’ to ‘8’) represents how many mines are adjacent to this revealed square, and finally ‘X’ represents a revealed mine. Now given the next click position (row and column indices) among all the unrevealed squares (‘M’ or ‘E’), return the board after revealing this position according to the following rules:

  1. If a mine (‘M’) is revealed, then the game is over – change it to ‘X’.
  2. If an empty square (‘E’) with no adjacent mines is revealed, then change it to revealed blank (‘B’) and all of its adjacent unrevealed squares should be revealed recursively.
  3. If an empty square (‘E’) with at least one adjacent mine is revealed, then change it to a digit (‘1’ to ‘8’) representing the number of adjacent mines.
  4. Return the board when no more squares will be revealed.
Example 1:
Input:
[['E', 'E', 'E', 'E', 'E'],
 ['E', 'E', 'M', 'E', 'E'],
 ['E', 'E', 'E', 'E', 'E'],
 ['E', 'E', 'E', 'E', 'E']]
Click : [3,0]
Output:
[['B', '1', 'E', '1', 'B'],
 ['B', '1', 'M', '1', 'B'],
 ['B', '1', '1', '1', 'B'],
 ['B', 'B', 'B', 'B', 'B']]
Explanation:

Example 2:
Input:
[['B', '1', 'E', '1', 'B'],
 ['B', '1', 'M', '1', 'B'],
 ['B', '1', '1', '1', 'B'],
 ['B', 'B', 'B', 'B', 'B']]
Click : [1,2]
Output:
[['B', '1', 'E', '1', 'B'],
 ['B', '1', 'X', '1', 'B'],
 ['B', '1', '1', '1', 'B'],
 ['B', 'B', 'B', 'B', 'B']]
Explanation:

Note:
  1. The range of the input matrix’s height and width is [1,50].
  2. The click position will only be an unrevealed square (‘M’ or ‘E’), which also means the input board contains at least one clickable square.
  3. The input board won’t be a stage when game is over (some mines have been revealed).
  4. For simplicity, not mentioned rules should be ignored in this problem. For example, you don’t need to reveal all the unrevealed mines when the game is over, consider any cases that you will win the game or flag any squares.

扫雷。给定一个棋盘和点击的坐标,要求给出点击之后新的棋盘布局。 为了做这个题,玩了一上午的扫雷。。。 更新规则很简单:
  1. 如果周围(上下左右和四个对角)没有雷,则该位置写’B’,并且递归的在周围模拟点击
  2. 如果周围有雷,则在该位置写上周围有雷的数目
  3. 如果点中了雷,则写上’X’,游戏结束
简单题,使用DFS,遇到以上第1条规则时,递归DFS。 代码如下: [cpp] class Solution { private: void dfs(vector<vector<char>>& board, int i, int j) { if (board[i][j] == ‘E’) { int m = board.size(), n = board[0].size(); vector<vector<int>> dirs = { { -1,0 },{ 1,0 },{ 0,-1 },{ 0,1 },{ -1,-1 },{ -1,1 },{ 1,-1 },{ 1,1 } }; int mines = 0; for (int k = 0; k < dirs.size(); ++k) { int x = i + dirs[k][0], y = j + dirs[k][1]; if (x >= 0 && x < m&&y >= 0 && y < n&&board[x][y] == ‘M’)++mines; } if (mines == 0) { board[i][j] = ‘B’; for (int k = 0; k < dirs.size(); ++k) { int x = i + dirs[k][0], y = j + dirs[k][1]; if (x >= 0 && x < m&&y >= 0 && y < n)dfs(board, x, y); } } else board[i][j] = ‘0’ + mines; } } public: vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) { if (board[click[0]][click[1]] == ‘M’) { board[click[0]][click[1]] = ‘X’; return board; } dfs(board, click[0], click[1]); return board; } }; [/cpp] 本代码提交AC,用时12MS。]]>

LeetCode Convert BST to Greater Tree

LeetCode Convert BST to Greater Tree Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST is changed to the original key plus sum of all keys greater than the original key in BST. Example:

Input: The root of a Binary Search Tree like this:
              5
            /   \
           2     13
Output: The root of a Greater Tree like this:
             18
            /   \
          20     13

给定一棵二叉搜索树,要求把每个点的值换成BST中大于等于该点的其他所有点的值之和。 很有意思的一个题,因为BST满足左<=根<=右,则比某个点大的点在其根节点和右兄弟上,为了得到根节点和右兄弟节点之和,可以采用右->根->左的遍历顺序,也就是和先序遍历正好相反的顺序遍历BST,同时记录遍历过的数之和。 代码如下: [cpp] class Solution { private: void revPreOrder(TreeNode* root, int& sum) { if (root->right)revPreOrder(root->right, sum); sum += root->val; root->val = sum; if (root->left)revPreOrder(root->left, sum); } public: TreeNode* convertBST(TreeNode* root) { if (!root)return NULL; int sum = 0; revPreOrder(root, sum); return root; } }; [/cpp] 本代码提交AC,用时46MS。]]>