Category Archives: LeetCode

LeetCode Next Greater Element III

LeetCode Next Greater Element III Given a positive 32-bit integer n, you need to find the smallest 32-bit integer which has exactly the same digits existing in the integer n and is greater in value than n. If no such positive 32-bit integer exists, you need to return -1. Example 1:

Input: 12
Output: 21
Example 2:
Input: 21
Output: -1

给定一个数n,要求用和n一样的数字,重组成一个比n大的最小的数。如果不存在这样的数,输出-1。 比如样例1,n=12,则同样用数字1和2,重组出比12大的最小的数就是21。如果n本身等于21,则无法用数字1和2重组出比21更大的数了。 首先很容易想到无解的情况,比如n=76543210,因为n的数字从左到右是非升序的,所以n本身已经是最大的了,无法重组出比n更大的数。所以隐隐约约感觉可以从左往右找第一个上升的位置。 再来,n=76546743,如果从左往右找第一个上升的位置,则是i=3的数字4,4->6是上升的,所以可以考虑从4后面找比4大的最小的数,也就是6,交换4和6,变成76564743,因为原来为4的位置已经变成更大的6了,所以6后面最小即可,对6后面的数排序,变成了76563447。 但是76563447并不是比n大的最小的数,另外还有76547346,也就是不变4,而是变i=4的数字6。所以换一种思路,我们从右往左找第一个下降的位置,比如这里是i=5的数字7,然后从该位置往右找一个比i-1的数6大的最小的数7,交换他们的位置,同时把i-1右边的数从小到大排序。 再比如n=12443322,从右往左找第一个下降的位置是i=2,数字为4,从该位置找一个比i-1的数2大的最小的数是i=4的数3,交换他们n=1344222,再对i-1右边的数从小到大排序,得到n=1322244。 完整代码如下,另外需要注意结果不能超出int范围,所以先转换为long long,再和INT_MAX比较。 [cpp] class Solution { public: int nextGreaterElement(int n) { string s = to_string(n); int m = s.size(); for (int i = m – 1; i > 0; –i) { if (s[i] > s[i – 1]) { int pos = i; for (int j = i; j < m; ++j) { if (s[j] > s[i – 1] && s[j] < s[pos]) { pos = j; } } swap(s[pos], s[i – 1]); sort(s.begin() + i, s.end()); long long ans = stoll(s); if (ans <= INT_MAX)return ans; else return -1; } } return -1; } }; [/cpp] 本代码提交AC,用时3MS。]]>

LeetCode Design Excel Sum Formula

LeetCode Design Excel Sum Formula Your task is to design the basic function of Excel and implement the function of sum formula. Specifically, you need to implement the following functions: Excel(int H, char W): This is the constructor. The inputs represents the height and width of the Excel form. H is a positive integer, range from 1 to 26. It represents the height. W is a character range from ‘A’ to ‘Z’. It represents that the width is the number of characters from ‘A’ to W. The Excel form content is represented by a height * width 2D integer array C, it should be initialized to zero. You should assume that the first row of C starts from 1, and the first column of C starts from ‘A’.   void Set(int row, char column, int val): Change the value at C(row, column) to be val.   int Get(int row, char column): Return the value at C(row, column).   int Sum(int row, char column, List of Strings : numbers): This function calculate and set the value at C(row, column), where the value should be the sum of cells represented by numbers. This function return the sum result at C(row, column). This sum formula should exist until this cell is overlapped by another value or another sum formula. numbers is a list of strings that each string represent a cell or a range of cells. If the string represent a single cell, then it has the following format : ColRow. For example, “F7” represents the cell at (7, F). If the string represent a range of cells, then it has the following format : ColRow1:ColRow2. The range will always be a rectangle, and ColRow1 represent the position of the top-left cell, and ColRow2 represents the position of the bottom-right cell.   Example 1:

Excel(3,"C");
// construct a 3*3 2D array with all zero.
//   A B C
// 1 0 0 0
// 2 0 0 0
// 3 0 0 0
Set(1, "A", 2);
// set C(1,"A") to be 2.
//   A B C
// 1 2 0 0
// 2 0 0 0
// 3 0 0 0
Sum(3, "C", ["A1", "A1:B2"]);
// set C(3,"C") to be the sum of value at C(1,"A") and the values sum of the rectangle range whose top-left cell is C(1,"A") and bottom-right cell is C(2,"B"). Return 4.
//   A B C
// 1 2 0 0
// 2 0 0 0
// 3 0 0 4
Set(2, "B", 2);
// set C(2,"B") to be 2. Note C(3, "C") should also be changed.
//   A B C
// 1 2 0 0
// 2 0 2 0
// 3 0 0 6
Note:
  1. You could assume that there won’t be any circular sum reference. For example, A1 = sum(B1) and B1 = sum(A1).
  2. The test cases are using double-quotes to represent a character.
  3. Please remember to RESET your class variables declared in class Excel, as static/class variables are persisted across multiple test cases. Please see here for more details.

本题要求设计一个简单的Excel表格求和功能。主要实现三个接口:
  • Get(int row, char column),获取坐标为(row,column)的cell的值
  • Set(int row, char column, int val),把坐标为(row,column)的值设置为val
  • Sum(int row, char column, List of Strings : numbers),numbers表示一系列求和公式,把公式计算结果填入坐标(row,column)中,并且当公式中的格子更新时,该公式计算出来的值也要更新。
本题的难点是,如果C3=A1+B2,如果更新了B2,下次get(C3)时,得到的结果也必须是用更新过的B2的值。而且还有可能A1的值也是用某个公式计算出来的。 当时比赛的时候,有一些思路,但是逻辑不是很清晰,后来参考这个题解,逻辑很清楚。 Excel包含两个成员,二维矩阵matrix表示一个excel表格,hashmap formula的key为某个格子,value为该格子对应的求和公式。如果某个格子的值是实实在在的值,不是用公式计算出来的,则不在这个hashmap中。
  • 对于get,如果坐标不在formula中,说明该格子是实实在在的值,直接返回matrix中的值。否则需要从formula中取出求和公式进行计算。
  • 对于set,直接把matrix对应坐标设置为value就好,注意的是,因为set之后就变成了实实在在的值,所以要清空formula中该格子的公式(如果有的话)。
  • 对于sum,计算字符串公式的值,把结果填入对应的格子,然后在formula中设置该格子的公式。
问题的难点是怎样对一个公式求值。说穿了其实就是不停的递归调用get函数,因为get函数如果该cell没有在formula中,则返回实实在在的值,否则递归计算formula的值。想象一下,就是不停的对一个坐标递归求值,直到不能递归时,返回matrix中的值,然后递归累加起来。想明白了其实很简单,代码注意把公共的计算部分抽象出来。 完整代码如下: [cpp] class Excel { private: vector<vector<int>> matrix; unordered_map<int, vector<string>> formula; // 把坐标hash成一个int int id(int r, char c) { return r * 27 + c – ‘A’ + 1; } void parse(string& s, int& r, char& c) { c = s[0]; r = stoi(s.substr(1)); } int get_cell(string& s) { int r; char c; parse(s, r, c); return get(r, c); } int get_range(string& s) { size_t pos = s.find(‘:’); string s1 = s.substr(0, pos), s2 = s.substr(pos + 1); int r1, r2; char c1, c2; parse(s1, r1, c1); parse(s2, r2, c2); int ans = 0; for (int i = r1; i <= r2; ++i) { for (char c = c1; c <= c2; ++c) { ans += get(i, c); } } return ans; } int get_cells(vector<string>& strs) { int ans = 0; for (auto& s : strs) { if (s.find(‘:’) == string::npos) ans += get_cell(s); else ans += get_range(s); } return ans; } public: Excel(int H, char W) { matrix.clear(); formula.clear(); for (int i = 0; i <= H; ++i) { matrix.push_back(vector<int>(W – ‘A’ + 1, 0)); } } void set(int r, char c, int v) { matrix[r][c - 'A'] = v; formula.erase(id(r, c)); // caution } int get(int r, char c) { if (formula.find(id(r, c)) == formula.end())return matrix[r][c - 'A']; return get_cells(formula[id(r, c)]); } int sum(int r, char c, vector<string> strs) { int ans = get_cells(strs); matrix[r][c - 'A'] = ans; formula[id(r, c)] = strs; return ans; } }; [/cpp] 本代码提交AC,用时6MS。]]>

LeetCode K Inverse Pairs Array

LeetCode K Inverse Pairs Array Given two integers n and k, find how many different arrays consist of numbers from 1 to n such that there are exactly k inverse pairs. We define an inverse pair as following: For ith and jth element in the array, if i < j and a[i] > a[j] then it’s an inverse pair; Otherwise, it’s not. Since the answer may very large, the answer should be modulo 109 + 7. Example 1:

Input: n = 3, k = 0
Output: 1
Explanation:
Only the array [1,2,3] which consists of numbers from 1 to 3 has exactly 0 inverse pair.
Example 2:
Input: n = 3, k = 1
Output: 2
Explanation:
The array [1,3,2] and [2,1,3] have exactly 1 inverse pair.
Note:
  1. The integer n is in the range [1, 1000] and k is in the range [0, 1000].

给定一个长度为n的,包含1~n这n个数的数组,问使得逆序对有k个的数组排列有多少种。 使用DP求解。假设dp[n][k]表示长度为n的数组,有k个逆序对的排列数,则: dp[n+1][k]=dp[n][k]+dp[n][k-1]+dp[n][k-2]+…+dp[n][k-n] 要求n+1长有k个逆序对的排列数,可以在
  • 长度为n,且有k个逆序对的基础上,把第n+1个数放到原序列的末尾,则不增加逆序对,+dp[n][k],xxxx*(xxxx表示原长度为n的序列,*表示新加入的数)
  • 长度为n,且有k-1个逆序对的基础上,把第n+1个数插入到原序列倒数第一个空位上,xxx*x,因为插入的*是最大的数,和最后一个x形成一个逆序对,使得新的长度为n+1的序列的逆序对=k-1+1=k,所以+dp[n][k-1]
  • 类似的,xx*xx,+dp[n][k-2]
  • x*xxx,+dp[n][k-3]
  • *xxxx,+dp[n][k-4]
因为远序列长度为n,所以插入的*最多只能增加n个逆序对,即上面的最后一种情况,所以原序列至少需要k-n个逆序对,这样插入*之后,才能达到k-n+n=k个逆序对。即以上递推式的最后一项是dp[n][k-n]。 完整代码如下,注意代码中i其实是n+1,所以m的下界是k-n=j-(i-1)=j-i+1,所以m>j-i。 [cpp] const int kMOD = 1000000007; class Solution { public: int kInversePairs(int n, int k) { vector<vector<long long>> dp(n + 1, vector<long long>(k + 1, 0)); dp[1][0] = 1; // 长度为1,逆序对为0,只有一种情况 for (int i = 2; i <= n; ++i) { for (int j = 0; j <= k; ++j) { for (int m = j; m >= 0 && m > j – i; –m) { dp[i][j] += dp[i – 1][m]; } dp[i][j] %= kMOD; } } return dp[n][k]; } }; [/cpp] 本代码提交AC,用时1065MS。时空都还可以优化。 参考:https://discuss.leetcode.com/topic/93710/java-dp-thank-you-so-much-gardenaaa-for-your-advice]]>

LeetCode Course Schedule III

LeetCode Course Schedule III There are n different online courses numbered from 1 to n. Each course has some duration(course length) t and closed on dth day. A course should be taken continuously for t days and must be finished before or on the dth day. You will start at the 1st day. Given n online courses represented by pairs (t,d), your task is to find the maximal number of courses that can be taken. Example:

Input: [[100, 200], [200, 1300], [1000, 1250], [2000, 3200]]
Output: 3
Explanation:
There're totally 4 courses, but you can take 3 courses at most:
First, take the 1st course, it costs 100 days so you will finish it on the 100th day, and ready to take the next course on the 101st day.
Second, take the 3rd course, it costs 1000 days so you will finish it on the 1100th day, and ready to take the next course on the 1101st day.
Third, take the 2nd course, it costs 200 days so you will finish it on the 1300th day.
The 4th course cannot be taken now, since you will finish it on the 3300th day, which exceeds the closed date.
Note:
  1. The integer 1 <= d, t, n <= 10,000.
  2. You can’t take two courses simultaneously.

给定一系列课程,每门课有持续时间以及该课程关闭时间。从0时刻开始,问最多能完成多少门课程。注意不能同时上多门课程。 使用贪心的思路, 首先根据经验,越早结束的课程,越早选修并结束该课程越好,因为这样可以留出更多的时间选修其他课程。所以我们首先对所有课程按关闭时间从小到大排序,每次我们贪心的选择最早关闭的课程。 如果now+duration<=closed,即当前时间加该课程的持续时间不超过课程的关闭时间,则贪心选修该课程,并且把该课程的持续时间插入到一个优先队列中(最大堆)。 如果不能选修该课程,且优先队列中堆顶的持续时间比当前课程还大,则可以把堆顶课程删掉,换成该门课程,这样该门课程肯定可以选修并完成,同时使得新的now比之前的now要小,更有利于选修更多的课程。 举个例子,假设已经按关闭时间排序了[3,8],[7,10],[5,14],[8,17],now=0。
  1. 选修第一门课程,now=3<8,优先队列堆顶为3
  2. 选修第二门课程,now=3+7=10<=10,优先队列堆顶为7
  3. 选修第三门课程,now=10+5=15>14,失败;发现堆顶课程的持续时间是7,大于当前课程的持续时间5,所以可以把堆顶课程换成该门课程,则新的now=10-7+5=8,堆顶为5。因为该门课程的持续时间比堆顶短,且关闭时间已排序,所以大于堆顶的关闭时间,所以把堆顶课程换成该课程,该课程肯定能过完成。且新的now=8比先前的now=10要小,使得可以完成第四门课程。
  4. 选修第四门课,now=8+8=16<17,优先队列为8。
完整代码如下: [cpp] class Solution { public: int scheduleCourse(vector<vector<int>>& courses) { auto cmp = [](vector<int>& c1, vector<int>& c2) {return c1[1] < c2[1]; }; sort(courses.begin(), courses.end(), cmp); int now = 0, ans = 0; priority_queue<int> pq; for (const auto& c : courses) { if (now + c[0] <= c[1]) { ++ans; now += c[0]; pq.push(c[0]); } else if (!pq.empty() && c[0] < pq.top()) { now = now – pq.top() + c[0]; pq.pop(); pq.push(c[0]); } } return ans; } }; [/cpp] 本代码提交AC,用时162MS。]]>

LeetCode Maximum Product of Three Numbers

LeetCode Maximum Product of Three Numbers Given an integer array, find three numbers whose product is maximum and output the maximum product. Example 1:

Input: [1,2,3]
Output: 6
Example 2:
Input: [1,2,3,4]
Output: 24
Note:
  1. The length of the given array will be in range [3,104] and all elements are in the range [-1000, 1000].
  2. Multiplication of any three numbers in the input won’t exceed the range of 32-bit signed integer.

给定一个整数数组,选出三个数,使得乘积最大。 整数数组中可能有负数,所以我们先对数组从小到大排序。如果最小值都大于0,说明没有负数,则三数乘积最大就是最大的前3个数的乘积。 如果有负数,且至少有两个负数,则还需要判断一下最小的两个负数乘以最大的正数的乘积,这个数和前一种情况的大小关系。 代码如下: [cpp] class Solution { public: int maximumProduct(vector<int>& nums) { int n = nums.size(); sort(nums.begin(), nums.end()); int ans1 = nums[n – 1] * nums[n – 2] * nums[n – 3], ans2 = 0; if (nums[0] > 0)return ans1; if (nums[0] < 0 && nums[1] < 0)ans2 = nums[0] * nums[1] * nums[n – 1]; return max(ans1, ans2); } }; [/cpp] 本代码提交AC,用时73MS。]]>

LeetCode Basic Calculator II

LeetCode Basic Calculator II Implement a basic calculator to evaluate a simple expression string. The expression string contains only non-negative integers, +, -, *, / operators and empty spaces . The integer division should truncate toward zero. You may assume that the given expression is always valid. Some examples:

"3+2*2" = 7
" 3/2 " = 1
" 3+5 / 2 " = 5
Note: Do not use the eval built-in library function.
本题是LeetCode Basic Calculator的简化版,去掉了括号,增加了乘除法。但是算法都是一模一样的,先把中缀转换为后缀,然后用栈求值。 代码如下: [cpp] // 优先级 unordered_map<string, int> priority = { {"+", 1},{"-", 1},{"*", 2},{"/", 2} }; class Solution { private: void push(stack<string> &numbers, stack<string> &opers, const string& numOrop) { if (isdigit(numOrop[0])) { numbers.push(numOrop); } else { if (numOrop == ")") { while (opers.top() != "(") { numbers.push(opers.top()); opers.pop(); } opers.pop(); } else if (numOrop == "(") { opers.push(numOrop); } else if (opers.empty() || opers.top() == "(") { opers.push(numOrop); } else if (priority[numOrop] > priority[opers.top()]) { opers.push(numOrop); } else { while (!opers.empty() && opers.top() != "(" && priority[numOrop] <= priority[opers.top()]) { numbers.push(opers.top()); opers.pop(); } opers.push(numOrop); } } } // 中缀转后缀表达式 list<string> in2post(const string& s) { stack<string> numbers, opers; int start = 0, end = 1, n = s.size(); while (start < n) { while (start < n&&s[start] == ‘ ‘)++start; if (start >= n)break; if (isdigit(s[start])) { end = start + 1; while (end < n&&isdigit(s[end]))++end; string num = s.substr(start, end – start); push(numbers, opers, num); start = end; } else { string op = string(1, s[start]); push(numbers, opers, op); ++start; } } while (!opers.empty()) { numbers.push(opers.top()); opers.pop(); } list<string> ans; while(!numbers.empty()) { ans.push_front(numbers.top()); numbers.pop(); } return ans; } // 求值后缀表达式的值 int eval(list<string>& post) { int ans = 0; stack<int> numbers; for (const auto& s : post) { if (priority.find(s) != priority.end()) { int num2 = numbers.top(); numbers.pop(); int num1 = numbers.top(); numbers.pop(); if (s == "+")numbers.push(num1 + num2); else if (s == "-")numbers.push(num1 – num2); else if (s == "*")numbers.push(num1*num2); else numbers.push(num1 / num2); } else numbers.push(stoi(s)); } return numbers.top(); } public: int calculate(string s) { list<string> ans = in2post(s); return eval(ans); } }; [/cpp] 本代码提交AC,用时85MS。]]>

LeetCode Basic Calculator

224. Basic Calculator 224. Basic Calculator

Implement a basic calculator to evaluate a simple expression string.

The expression string may contain open ( and closing parentheses ), the plus + or minus sign -non-negative integers and empty spaces .

Example 1:

Input: "1 + 1"
Output: 2

Example 2:

Input: " 2-1 + 2 "
Output: 3

Example 3:

Input: "(1+(4+5+2)-3)+(6+8)"
Output: 23

Note:

  • You may assume that the given expression is always valid.
  • Do not use the eval built-in library function.

给定一个字符串表达式,要求求解该表达式的值。 使用栈解决。我们通常看到的表达式称为中缀表达式,需要把它转换为后缀表达式,比如1+((2+3)×4)-5转换为1 2 3 + 4 × + 5 -。我们可以很容易用栈求解后缀表达式,只需要遍历后缀表达式,把遇到的操作数压栈,只要遇到运算符,就从栈中弹出两个操作数,进行运算,再把运算结果压栈。最后栈中只能得到一个值,就是整个表达式的值。 所以问题的关键就是怎样把中缀表达式转换为后缀表达式。 使用两个栈,一个栈保存操作数numbers,另一个栈保存运算符opers。遍历原字符串,按如下规则进行压栈和弹栈:

  • 如果是操作数,直接压入numbers
  • 如果是操作符op:
    1. 如果op为左括号“(”,则直接把op压入opers
    2. 如果op为右括号“)”,则把opers的运算符不断弹栈并压入numbers,直到栈顶为左括号“(”,此时将这一对括号丢弃
    3. 如果opers为空,或者opers栈顶为左括号“(”,则直接把op压入opers
    4. 此时,栈顶肯定不可能是括号了,如果op的优先级高于opers栈顶的优先级,则直接把op压入opers
    5. 否则,把opers栈顶的运算符不断弹栈并压入numbers,直到栈顶为左括号,或者op的优先级高于opers栈顶的优先级。把op压入opers

如果是操作符op,下面的1~5的判断规则是有先后顺序的,需要先判断是否为括号,再判断是否是一般的运算符。 运算符的优先级是,+-优先级相同,*/优先级相同,且+-的优先级低于*/。 得到中缀表达式的后缀表达式之后,再用开头提到的栈求解。后缀表达式的求值就非常简单了。 完整代码如下:

// 优先级
unordered_map<string, int> priority = { { "+", 1 }, { "-", 1 }, { "*", 2 }, { "/", 2 } };
class Solution {
private:
    void push(stack<string>& numbers, stack<string>& opers, const string& numOrop)
    {
        if (isdigit(numOrop[0])) {
            numbers.push(numOrop);
        }
        else {
            if (numOrop == ")") {
                while (opers.top() != "(") {
                    numbers.push(opers.top());
                    opers.pop();
                }
                opers.pop();
            }
            else if (numOrop == "(") {
                opers.push(numOrop);
            }
            else if (opers.empty() || opers.top() == "(") {
                opers.push(numOrop);
            }
            else if (priority[numOrop] > priority[opers.top()]) {
                opers.push(numOrop);
            }
            else {
                while (!opers.empty() && opers.top() != "(" && priority[numOrop] <= priority[opers.top()]) {
                    numbers.push(opers.top());
                    opers.pop();
                }
                opers.push(numOrop);
            }
        }
    }
    // 中缀转后缀表达式
    list<string> in2post(const string& s)
    {
        stack<string> numbers, opers;
        int start = 0, end = 1, n = s.size();
        while (start < n) {
            while (start < n && s[start] == ‘ ‘)
                ++start;
            if (start >= n)
                break;
            if (isdigit(s[start])) {
                end = start + 1;
                while (end < n && isdigit(s[end]))
                    ++end;
                string num = s.substr(start, end – start);
                push(numbers, opers, num);
                start = end;
            }
            else {
                string op = string(1, s[start]);
                push(numbers, opers, op);
                ++start;
            }
        }
        while (!opers.empty()) {
            numbers.push(opers.top());
            opers.pop();
        }
        list<string> ans;
        while (!numbers.empty()) {
            ans.push_front(numbers.top());
            numbers.pop();
        }
        return ans;
    }
    // 求值后缀表达式的值
    int eval(list<string>& post)
    {
        int ans = 0;
        stack<int> numbers;
        for (const auto& s : post) {
            if (priority.find(s) != priority.end()) {
                int num2 = numbers.top();
                numbers.pop();
                int num1 = numbers.top();
                numbers.pop();
                if (s == "+")
                    numbers.push(num1 + num2);
                else if (s == "-")
                    numbers.push(num1 – num2);
                else if (s == "*")
                    numbers.push(num1 * num2);
                else
                    numbers.push(num1 / num2);
            }
            else
                numbers.push(stoi(s));
        }
        return numbers.top();
    }
public:
    int calculate(string s)
    {
        list<string> ans = in2post(s);
        return eval(ans);
    }
};

本代码提交AC,用时92MS。
参考:http://blog.csdn.net/antineutrino/article/details/6763722

二刷。push函数实际上只有3个分支就可以了,上面的过于复杂,看下面:

unordered_map<string, int> priority = { {"+",1},{"-",1},{"*",2},{"/",2} };

class Solution {
private:
	bool IsDigit(char c) {
		return c >= '0'&&c <= '9';
	}

	vector<string> ParseString(const string &s) {
		vector<string> vec;
		int n = s.size();
		int i = 0, j = 0;
		while (i < n) {
			while (i < n&&s[i] == ' ')++i;
			if (i >= n)break;

			if (!IsDigit(s[i])) {
				vec.push_back(string(1, s[i]));
				++i;
			}
			else {
				j = i + 1;
				while (j < n&&IsDigit(s[j]))++j;
				vec.push_back(s.substr(i, j - i));
				i = j;
			}
		}
		return vec;
	}

	list<string> In2Post(const vector<string> &vec) {
		stack<string> numbers, opers;
		for (int i = 0; i < vec.size(); ++i) {
			if (IsDigit(vec[i][0])) {
				numbers.push(vec[i]);
			}
			else {
				if (vec[i] == ")") { // 右括号
					while (opers.top() != "(") {
						numbers.push(opers.top());
						opers.pop();
					}
					opers.pop();
				}
				else if (vec[i] == "(") { // 左括号
					opers.push(vec[i]);
				}
				else { // 操作符
					while (!opers.empty() && opers.top() != "("&&priority[vec[i]] <= priority[opers.top()]) {
						numbers.push(opers.top());
						opers.pop();
					}
					opers.push(vec[i]);
				}
			}
		}
		
		while (!opers.empty()) {
			numbers.push(opers.top());
			opers.pop();
		}
		list<string> lst;
		while (!numbers.empty()) {
			lst.push_front(numbers.top());
			numbers.pop();
		}
		return lst;
	}

	int Evaluate(const list<string> &lst) {
		stack<string> stk;
		for (list<string>::const_iterator it = lst.begin(); it != lst.end(); ++it) {
			if (IsDigit((*it)[0])) {
				stk.push(*it);
			}
			else {
				int b = atoi(stk.top().c_str());
				stk.pop();
				int a= atoi(stk.top().c_str());
				stk.pop();
				if (*it == "+") {
					stk.push(to_string(a + b));
				}
				else if (*it == "-") {
					stk.push(to_string(a - b));
				}
			}
		}
		return atoi(stk.top().c_str());
	}

public:
	int calculate(string s) {

		vector<string> vec = ParseString(s);
		list<string> lst = In2Post(vec);
		return Evaluate(lst);
	}
};

本代码提交AC,用时312MS。

LeetCode Mini Parser

LeetCode Mini Parser Given a nested list of integers represented as a string, implement a parser to deserialize it. Each element is either an integer, or a list — whose elements may also be integers or other lists. Note: You may assume that the string is well-formed:

  • String is non-empty.
  • String does not contain white spaces.
  • String contains only digits 0-9, [, - ,, ].
Example 1:
Given s = "324",
You should return a NestedInteger object which contains a single integer 324.
Example 2:
Given s = "[123,[456,[789]]]",
Return a NestedInteger object containing a nested list with 2 elements:
1. An integer containing value 123.
2. A nested list containing two elements:
    i.  An integer containing value 456.
    ii. A nested list with one element:
         a. An integer containing value 789.

给定一个嵌套的字符串,要求把它解析成一个NestedInteger。 解法1,使用栈。遇到左括号时,增加一个空的NestedInteger实例,压栈。遇到逗号时,把前面的数add到栈顶的NestedInteger中。遇到右括号时,把栈顶的NestedInteger弹栈,并add到新的栈顶(相当于前一个)NestedInteger中。最后栈顶只有一个元素,返回该元素即可。 代码如下: [cpp] class Solution { public: NestedInteger deserialize(string s) { auto isnumber = [](char c) {return c == ‘-‘ || isdigit(c); }; stack<NestedInteger> stk; stk.push(NestedInteger()); for (auto it = s.begin(); it != s.end();) { if (isnumber(*it)) { auto it2 = find_if_not(it, s.end(), isnumber); int v = stoi(string(it, it2)); stk.top().add(NestedInteger(v)); it = it2; } else { if (*it == ‘[‘) { stk.push(NestedInteger()); } else if (*it == ‘]’) { NestedInteger tmp = stk.top(); stk.pop(); stk.top().add(tmp); } ++it; } } return stk.top().getList().front(); } }; [/cpp] 本代码提交AC,用时19MS。 解法2,递归法。如果当前的字符串是一个裸的整数的话,类似于样例1,则直接返回以该数为参数的NestedInteger;否则剥掉左括号[,递归反序列化,把递归的结果add到当前的NestedInteger中。 代码如下: [cpp] class Solution { private: NestedInteger deserialize(istringstream &in) { int number; if (in >> number) return NestedInteger(number); in.clear(); in.get(); NestedInteger list; while (in.peek() != ‘]’) { list.add(deserialize(in)); if (in.peek() == ‘,’)in.get(); } in.get(); return list; } public: NestedInteger deserialize(string s) { istringstream in(s); return deserialize(in); } }; [/cpp] 本代码提交AC,用时19MS。 参考1,栈:https://discuss.leetcode.com/topic/54904/c-non-recursive-one-pass-solution-using-stack-a-possible-implementation-of-nestedinteger 参考2,递归:https://discuss.leetcode.com/topic/54258/python-c-solutions/10]]>

LeetCode Unique Substrings in Wraparound String

LeetCode Unique Substrings in Wraparound String Consider the string s to be the infinite wraparound string of “abcdefghijklmnopqrstuvwxyz”, so s will look like this: “…zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd….”. Now we have another string p. Your job is to find out how many unique non-empty substrings of p are present in s. In particular, your input is the string p and you need to output the number of different non-empty substrings of p in the string s. Note: p consists of only lowercase English letters and the size of p might be over 10000. Example 1:

Input: "a"
Output: 1
Explanation: Only the substring "a" of string "a" is in the string s.
Example 2:
Input: "cac"
Output: 2
Explanation: There are two substrings "a", "c" of string "cac" in the string s.
Example 3:
Input: "zab"
Output: 6
Explanation: There are six substrings "z", "a", "b", "za", "ab", "zab" of string "zab" in the string s.

给定一个a-z的无限循环字符串s,比如…zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd….。再给定一个字符串p,问p有多少个子串是在s中的。 在s中的子串需要满足一定的条件,比如单个字符可以,还有就是连续的字符串,即abcd…之类的。 注意第二个样例中,p有两个相同的子串c,但是结果中只统计一次,所以比如p中有多个以同一个字符结尾的子串,我们只需要统计最长的那个就好了。比如P=”abcdefgxxxxcdefgyyy”。以g结尾的连续子串有两个,分别是abcdefg和cdefg,但是我们只需要保留前者就好了,因为前者最长,它的所有子串已经包含后者的所有子串了。而子串的长度就是以g为结尾且在s中的子串的长度,比如这里就是7。 所以我们只需要统计以每个字符结尾的最长连续子串的长度,然后把所有长度加起来,就是最终结果。 注意abcdefg以g结尾的长度是7,也就是abcdefg有7个子串是在s中的。abcdefg也包含abcdef,以f结尾的长度是6,也就是abcdef有6个子串在s中。 代码如下: [cpp] class Solution { public: int findSubstringInWraproundString(string p) { vector<int> count(26, 0); int len = 0; for (int i = 0; i < p.size(); ++i) { if (i > 0 && (p[i] – p[i – 1] == 1 || p[i] – p[i – 1] == -25))++len; else len = 1; count[p[i] – ‘a’] = max(count[p[i] – ‘a’], len); } int ans = 0; for (int i = 0; i < 26; ++i)ans += count[i]; return ans; } }; [/cpp] 本代码提交AC,用时9MS。]]>

LeetCode Maximal Square

221. Maximal Square

Given a 2D binary matrix filled with 0’s and 1’s, find the largest square containing only 1’s and return its area.

Example:

Input: 

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0

Output: 4

给定一个0,1矩阵,问矩阵中最大的全是1的正方形的面积是多少。 使用DP求解,假设dp[i][j]表示以点(i,j)为右下角的正方形的最大边长,则有dp[i][j]=min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1。
对于点(i,j),我们已经知道以该点的左边、上边和左上角的点为正方形右下角的点能得到的最大的正方形的边长。最好的情况是,如果这三个点能构成的最大正方形的边长相等,则加上点(i,j)之后,边长会扩大1。如下图红色的1,他的左边、上边和左上角的点为正方形右下角的点能得到的最大的正方形的边长都是2,所以加上该红色1之后,最大的边长变成了3。

0 0 0 0 0
0 1 1 1 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0

再比如红色1的左边那个点的边长只有1,则红色1最多只能扩展成边长为1+1的正方形。所以这个递推公式是合理的:dp[i][j]=min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1。

0 0 0 0 0
0 1 1 1 0
0 1 1 1 0
0 0 1 1 0
0 0 0 0 0

有递推公式就好办了,直接O(n^2)DP,代码如下:

class Solution {
public:
    int maximalSquare(vector<vector<char> >& matrix)
    {
        if (matrix.empty() || matrix[0].empty())
            return 0;
        int m = matrix.size(), n = matrix[0].size();
        vector<vector<int> > dp(m, vector<int>(n, 0));
        int maxLen = 0;
        for (size_t i = 0; i < m; ++i) {
            dp[i][0] = (matrix[i][0] == ‘1’ ? 1 : 0);
            maxLen = max(maxLen, dp[i][0]);
        }
        for (size_t j = 0; j < n; ++j) {
            dp[0][j] = (matrix[0][j] == ‘1’ ? 1 : 0);
            maxLen = max(maxLen, dp[0][j]);
        }
        for (size_t i = 1; i < m; ++i) {
            for (size_t j = 1; j < n; ++j) {
                if (matrix[i][j] == ‘1’) {
                    dp[i][j] = min(min(dp[i][j – 1], dp[i – 1][j]), dp[i – 1][j – 1]) + 1;
                    maxLen = max(maxLen, dp[i][j]);
                }
            }
        }
        return maxLen * maxLen;
    }
};

本代码提交AC,用时6MS。
因为dp[i][j]实际上只和之前的三个值有关,所以可以节省空间。代码如下:

class Solution {
public:
    int maximalSquare(vector<vector<char> >& matrix)
    {
        if (matrix.empty() || matrix[0].empty())
            return 0;
        int m = matrix.size(), n = matrix[0].size();
        vector<int> dp(n + 1, 0);
        int maxLen = 0, last_topleft = 0; // dp[i][j]的左上角那个值
        for (size_t i = 1; i <= m; ++i) {
            for (size_t j = 1; j <= n; ++j) {
                int tmp = dp[j];
                if (matrix[i – 1][j – 1] == ‘1’) {
                    dp[j] = min(min(dp[j], dp[j – 1]), last_topleft) + 1;
                    maxLen = max(maxLen, dp[j]);
                }
                else {
                    dp[j] = 0;
                }
                last_topleft = tmp;
            }
        }
        return maxLen * maxLen;
    }
};

本代码提交AC,用时6MS。