LeetCode - Algorithms - 224. Basic Calculator

Java

1

代码见前一篇

Submission Detail

  • 37 / 37 test cases passed.
  • Runtime: 143 ms
  • Your runtime beats 6.05 % of java submissions.

2 Shunting-yard algorithm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import java.util.StringTokenizer;

class Solution {
public int calculate(String s) {
return evalRPN(infixToPostfix(s.replaceAll(" ","")));
}

private int evalRPN(List<String> exprlist){
LinkedList<Integer> stack = new LinkedList<Integer>();

for (String token : exprlist) {
Integer tokenNum = null;
try{
tokenNum = Integer.parseInt(token);
}catch(NumberFormatException e){}
if(tokenNum != null){
stack.push(Integer.parseInt(token+""));
}else if(token.equals("-")){
int secondOperand = stack.pop();
int firstOperand = stack.pop();
stack.push(firstOperand - secondOperand);
}else if(token.equals("+")){
int secondOperand = stack.pop();
int firstOperand = stack.pop();
stack.push(firstOperand + secondOperand);
}else{
return 0;
}
}
int r = stack.pop();
return r;
}

private List<String> infixToPostfix(String infix) {
List<String> list = new ArrayList<String>();
final String ops = "-+";

Stack<Integer> stack = new Stack<Integer>();

StringTokenizer st = new StringTokenizer(infix,"[\\+\\-()]",true);
while (st.hasMoreTokens()) {
String token = st.nextToken();
if (token.isEmpty())
continue;
char c = token.charAt(0);
int idx = ops.indexOf(c);

if (idx != -1) {
if (stack.isEmpty())
stack.push(idx);

else {
while (!stack.isEmpty()) {
int prec2 = stack.peek() / 2;
int prec1 = idx / 2;
if (prec2 > prec1 || prec2 == prec1)
list.add( ops.charAt(stack.pop()) + "" );
else break;
}
stack.push(idx);
}
}
else if (c == '(') {
stack.push(-2);
}
else if (c == ')') {
while (stack.peek() != -2)
list.add( ops.charAt(stack.pop())+"" );
stack.pop();
}
else {
list.add( token );
}
}
while (!stack.isEmpty())
list.add( ops.charAt(stack.pop())+"" );
return list;
}
}

Submission Detail

  • 37 / 37 test cases passed.
  • Runtime: 172 ms, faster than 7.80% of Java online submissions for Basic Calculator.
  • Memory Usage: 55.4 MB, less than 20.00% of Java online submissions for Basic Calculator.

Resources

LeetCode - Algorithms - 227. Basic Calculator II

这题是关于表达式解析的,2007年学习数据结构曾经实现过,思路是把中缀表达式转换为后缀表达式,再结合栈这种数据结构计算后缀表达式,就拿来执行下,结果LeetCode test case 1*2-3/4+5*6-7*8+9/10 报了个错 java.lang.ArithmeticException: / by zero,用StringTokenizer把操作符与操作数拆开,改了下原来的代码,最终运行通过了,但自己对其中的机理还是有点知其然而不知其所以然。

原来java7以后可以在switch的case语句里用String类型。

Strings in switch Statements

In the JDK 7 release, you can use a String object in the expression of a switch statement.

Basic Calculator这系列的题看来也是比较经典的,表达式解析好像是数据结构与编译原理的交叉点之一。

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.StringTokenizer;

class Solution {
public int postfixCalculator(List<String> postfixExpr) {
Stack<Integer> stk = new Stack<Integer>();
for (int i = 0; i < postfixExpr.size(); i++) {
String s = postfixExpr.get(i);
int a, b, x;
switch (s) {
case "*":
if (!stk.isEmpty()) {
a = stk.pop().intValue();
b = stk.pop().intValue();
x = a * b;
stk.push(new Integer(x));
}
break;
case "+":
if (!stk.isEmpty()) {
a = stk.pop().intValue();
b = stk.pop().intValue();
x = a + b;
stk.push(new Integer(x));
}
break;
case "-":
if (!stk.isEmpty()) {
a = stk.pop().intValue();
b = stk.pop().intValue();
x = b - a;
stk.push(new Integer(x));
}
break;
case "/":
if (!stk.isEmpty()) {
a = stk.pop().intValue();
b = stk.pop().intValue();
x = b / a;
stk.push(new Integer(x));
}
break;
default:
stk.push(new Integer(s));
break;
}
}
int ret = 0;
if (!stk.isEmpty())
ret = stk.pop().intValue();
return ret;
}

public List<String> infix2postfix(String infixExpr) {
List<String> r = new ArrayList<String>();
Stack<String> stk = new Stack<String>();
List<String> list = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(infixExpr,"[\\+\\-\\*/()]",true);
while (st.hasMoreTokens()) {
list.add(st.nextToken());
}
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
switch (s) {
case "*":
case "/":
while (!stk.isEmpty() && (stk.peek().equals("*") || stk.peek().equals("/"))) {
r.add( stk.pop() );
}
stk.push(s);
break;
case "+":
case "-":
while (!stk.isEmpty() && !stk.peek().equals("(")) {
r.add( stk.pop() );
}
stk.push(s);
break;
case "(":
stk.push(s);
break;
case ")":
while (!stk.isEmpty() && !stk.peek().equals("(")) {
r.add(stk.pop());
}
if (stk.peek().equals("("))
stk.pop();
break;
default:
r.add(s);
}
}

while (stk != null && !stk.isEmpty()) {
r.add( stk.pop() );
}

return r;
}

public int calculate(String s) {
return postfixCalculator(infix2postfix(s.replaceAll(" ", "")));
}
}

Submission Detail

  • 109 / 109 test cases passed.
  • Runtime: 98 ms
  • Your runtime beats 5.79 % of java submissions.

LeetCode - Algorithms - 122. Best Time to Buy and Sell Stock II

自己已经意识到就是在输入数组里找递增子序列,但还是没想通。上网找点提示,参考了LeetCode – Best Time to Buy and Sell Stock II (Java),看了人家的,恍然大悟,不难,但就是想不到。

这系列 Best Time to Buy and Sell Stock 的题看来也是比较经典的

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public int maxProfit(int[] prices) {
int profit = 0;
int diff = 0;
for(int i=1;i<prices.length;i++) {
diff = prices[i]-prices[i-1];
if (diff>0) {
profit+=diff;
}
}
return profit;
}
}

Submission Detail

  • 201 / 201 test cases passed.
  • Your runtime beats 99.86 % of java submissions.

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function(prices) {
var profit = 0;
var diff = 0;
for(var i=1;i<prices.length;i++) {
diff = prices[i]-prices[i-1];
if (diff>0)
profit+=diff;
}
return profit;
};

Submission Detail

  • 201 / 201 test cases passed.
  • Your runtime beats 18.88 % of javascript submissions.

LeetCode - Algorithms - 121. Best Time to Buy and Sell Stock

虽然难度标为Easy,但自己居然提交了好几次才通过了,而且是因为犯了逻辑错误。最后用个二重循环,倒也简单,但性能不好,不知道高效算法是如何做的?

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int maxProfit(int[] prices) {
if (prices==null || prices.length==0)
return 0;
int r = 0;
for(int i=0;i<prices.length-1;i++) {
for(int j=prices.length-1;j>i;j--) {
if (prices[j]-prices[i]>r) {
r = prices[j]-prices[i];
}
}
}
return r;
}
}

Submission Detail

  • 200 / 200 test cases passed.
  • Your runtime beats 4.30 % of java submissions.

在网上人家的一个O(n)时间复杂度的算法

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public int maxProfit(int[] prices) {
if (prices==null || prices.length<=1)
return 0;
int r = 0;
int minPrice = prices[0];
for(int i=1;i<prices.length;i++) {
r = Math.max(r, prices[i]-minPrice);
minPrice = Math.min(minPrice, prices[i]);
}
return r;
}
}

Submission Detail

  • 200 / 200 test cases passed.
  • Your runtime beats 32.88 % of java submissions.

JavaScript

O(n2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function(prices) {
if (prices==null || prices.length==0)
return 0;
var r=0;
var x = 0;
for(var i=0;i<prices.length-1;i++) {
for(var j=prices.length-1;j>i;j--) {
x = prices[j]-prices[i];
if (x>r)
r = x;
}
}
return r;
};

Submission Detail

  • 200 / 200 test cases passed.
  • Your runtime beats 7.71 % of javascript submissions.

O(n)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function(prices) {
if (prices==null || prices.length<=1)
return 0;
var r=0;
var minPrice = prices[0];
for(var i=1;i<prices.length;i++) {
r = Math.max(r,prices[i]-minPrice);
minPrice = Math.min(minPrice,prices[i]);
}
return r;
};

Submission Detail

  • 200 / 200 test cases passed.
  • Your runtime beats 84.89 % of javascript submissions.

英语学习相关网站

听力

Voice of America - Learn American English with VOA Learning English
https://learningenglish.voanews.com/

BBC Learning English | Pronunciation Tips
http://www.bbc.co.uk/worldservice/learningenglish/grammar/pron/

60-Second Science
https://www.scientificamerican.com/podcast/60-second-science/

Videos & Podcasts - Scientific American
https://www.scientificamerican.com/multimedia/

TED Radio Hour
https://www.npr.org/programs/ted-radio-hour

BBC - World Service - Home
https://www.bbc.co.uk/worldserviceradio

Learning English - 6 Minute English
http://www.bbc.co.uk/worldservice/learningenglish/general/sixminute/

词典

Dictionary by Merriam-Webster: America’s most-trusted online dictionary
https://www.merriam-webster.com/

Collins Dictionary
https://www.collinsdictionary.com/

Dictionary.com
https://www.dictionary.com/

报刊

https://medium.com/

https://www.theatlantic.com/

https://www.newyorker.com/

https://www.npr.org/

https://www.economist.com/

https://www.bloomberg.com/businessweek

https://www.bloomberg.com/canada

https://www.theguardian.com/observer

https://www.theguardian.com/international

http://www.bbc.com/

https://www.telegraph.co.uk/

其他

A Free Online Talking Dictionary of English Pronunciation
https://www.howjsay.com/

UsingEnglish.com was established in 2002 and is a general English language site specialising in English as a Second Language (ESL).
https://www.usingenglish.com/

Discovery Canada
https://www.discovery.ca/Home

English Language & Usage Stack Exchange is a question and answer site for linguists, etymologists, and serious English language enthusiasts.
https://english.stackexchange.com/

LeetCode - Algorithms - 119. Pascal's Triangle II

118. Pascal’s Triangle 的变脸题,用递归的方式实现了,还没想通如何用动态规划的方式实现。

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public List<Integer> getRow(int rowIndex) {
List<Integer> list = new ArrayList<Integer>();
if (rowIndex==0) {
list.add(1);
return list;
}
if (rowIndex==1) {
list.add(1);
list.add(1);
return list;
}
if (rowIndex>=2) {
List<Integer> row_pre = getRow(rowIndex-1);
list.add(1);
for(int i=1;i<rowIndex;i++) {
list.add(row_pre.get(i)+row_pre.get(i-1));
}
list.add(1);
}
return list;
}
}

Submission Detail

  • 34 / 34 test cases passed.
  • Your runtime beats 89.30 % of java submissions.

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @param {number} rowIndex
* @return {number[]}
*/
var getRow = function(rowIndex) {
if (rowIndex==0) {
return [1];
}
if (rowIndex==1) {
return [1,1];
}
var arr = [];
if (rowIndex>=2) {
arr.push(1);
var preRow = getRow(rowIndex-1);
for(var i=1;i<rowIndex;i++)
arr.push(preRow[i]+preRow[i-1]);
arr.push(1);
}
return arr;
};

Submission Detail

  • 34 / 34 test cases passed.
  • Your runtime beats 93.58 % of javascript submissions.

LeetCode - Algorithms - 118. Pascal's Triangle

不难,不过写递归过程还是犯了些错误。 Pascal’s triangle 挺有名的,Binomial Coefficients好像是很重要的组合数学概念。

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> list = new ArrayList<List<Integer>>();

if (numRows==1) {
List<Integer> list0 = new ArrayList<Integer>();
list0.add(1);
list.add(list0);
return list;
}

if (numRows==2) {
List<Integer> list0 = new ArrayList<Integer>();
list0.add(1);
list.add(list0);
List<Integer> list1 = new ArrayList<Integer>();
list1.add(1);
list1.add(1);
list.add(list1);
return list;
}

if (numRows>=3) {
List<List<Integer>> list_= generate(numRows-1);
List<Integer> list_pre = list_.get(numRows-2);
for(int i=0;i<list_.size();i++)
list.add(list_.get(i));
List<Integer> list_curr = new ArrayList<Integer>();
list_curr.add(1);
for(int i=1;i<numRows-1;i++) {
list_curr.add(list_pre.get(i)+list_pre.get(i-1));
}
list_curr.add(1);
list.add(list_curr);
}
return list;
}

Submission Detail

  • 15 / 15 test cases passed.
  • Your runtime beats 100.00 % of java submissions.

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* @param {number} numRows
* @return {number[][]}
*/
var generate = function(numRows) {
if (numRows==1) {
return [[1]];
}
if (numRows==2) {
return [[1],[1,1]];
}
var arr = [];
if (numRows>=3) {
var arr_ = generate(numRows-1);
var line_pre = arr_[numRows-2];
for(i=0;i<arr_.length;i++)
arr.push(arr_[i]);
var line_curr = [1];
for(i=1;i<numRows-1;i++) {
line_curr.push(line_pre[i]+line_pre[i-1]);
}
line_curr.push(1);
arr.push(line_curr);
}
return arr;
};

Submission Detail

  • 15 / 15 test cases passed.
  • Your runtime beats 90.59 % of javascript submissions.

Better than the Four Colour Theorem - Jim Geelen - mathNEWS - VOLUME 135 • ISSUE 3 - October 20, 2017

There is a limpid mathematics journal at the University of Waterloo named mathNEWS, this essay was selected from that little journal. University of Waterloo’s campus has a street named William Tutte way near Davis Centre Library.


William Tutte spent enormous effort trying to solve the Four Colour Problem. Even after the computer-aided proof of Appel and Haken in 1976, Tutte continued working toward finding a short, human-readable, proof.

Tutte never did succeed, but he came close to achieving his goal on several occasions. For example, Tutte had significant insights into Tait’s Conjecture that three-connected cubic planar graphs are Hamiltonia n, which Tait had already shown to imply the Four Colour Conjecture. Unfortunately, instead of leading him to a proof, Tutte’s insights led him to discover a 46-vertex counter-example to Tait’s conjecture. Not long after that, Tutte proved that all four-connected planar graphs are Hamiltonian. While this is agonizingly close to Tait’s Conjecture, it does not have any immediate applications to colouring.

Tutte graph

Following those attempts, Tutte tried various algebraic approaches; one of these involved the chromatic polynomial of a graph. For a graph G and non-negative integer k, let \( \lambda_G(k) \) denote the number of colourings of G with colours 1, …, k. It is not at all obvious from this definition, but \( \lambda_G \) is a polynomial, which allows us to define it at values other than the positive integers.

The Four Colour Conjecture states that \( \lambda_G(4) > 0 \) whenever G is planar. If \( 0 \leq k_1 \leq k_2 \) are integers, then any \( k_1 \)-colouring is a \( k_2 \)-colouring, and hence \( \lambda_G(k_2) \geq \lambda_G(k_1) \). This property does not extend to non-negative real numbers, but it is conjectured that for each real number \( x \geq 4 \), we have \( \lambda_G(x) > 0 \) whenever G is planar. Tutte proved the following amazing result which superficially looks stronger than the Four Colour Theorem; in this result \( \tau \) is the golden ratio, so \( \tau+2=\frac{5+\sqrt{5}}{2} \approx 3.618 \).

The 3.618 Colour Theorem. For each planar graph G, we have
\( \lambda_G(\tau+2) > 0 \).

This year Gordon Royle proved that, if \( x < 4 \) is a real number such that \( \lambda_G(x) > 0 \) for each planar graph G, then \( x = \tau+2 \). Wow!

How on earth, you may ask, did Tutte come upon his result? It turns out that he came across the idea to try \( \tau+2 \) by empirical evidence. That evidence takes the form of eight large binders that are stored in the C&O library on the sixth floor of the MC building. Each of these binders contains, at a guess, around 500 pages. The pages alternate between a beautiful hand-drawn picture of a planar graph and a computer print out of the roots of its chromatic polynomial. Tutte enlisted the help of Ruth Bari and Dick Wick Hall to systematically generate the graphs and the help of Gerry Berman, founder of the C&O Department, to compute the chromatic roots. Nevertheless, it beggars belief to consider the work that Tutte put into drawing each of the graphs by hand and then trawling through these volumes for any patterns that might provide in-roads to the elusive Four Colour Conjecture. In the end he made do with only 3.618 colours.

This article is in memory of William T. Tutte, in this the centennial year of his birth. Among other honours, Tutte was a founding member of the C&O Department, a legendary World War II code breaker, and a hugely influential combinatorialist.

Jim Geelen


  • One of the most prolific graph theorists, William T. Tutte, judged the impact of the four-color theorem on mathematics by proclaiming: “The four-colour theorem is the tip of the iceberg, the thin end of the wedge, and the first cuckoo of Spring.” (The Princeton Companion to Mathematics - Part V Theorems and Problems - V.12 The Four-Color Theorem, by Bojan Mohar)
  • The Colorful Problem That Has Long Frustrated Mathematicians
  • I imagine one of them outgribing in despair, crying ‘What shall I do now?’ To which the proper answer is ‘Be of good cheer. You can continue in the same general line of research.’ - Bill Tutte

LeetCode - Algorithms - 171. Excel Sheet Column Number

这题算Easy,Excel列编号好像可以理解成26进制,少不了查下JDK API Specification,查看JavaScript Bible

Java

1
2
3
4
5
6
7
8
9
10
class Solution {
public int titleToNumber(String s) {
int n = 0;
int len = s.length();
for(int i=s.length()-1;i>=0;i--) {
n += (Character.getNumericValue(s.charAt(i))-9)*Math.pow(26, len-i-1);
}
return n;
}
}

Submission Detail

  • 1000 / 1000 test cases passed.
  • Your runtime beats 5.55 % of java submissions.

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
/**
* @param {string} s
* @return {number}
*/
var titleToNumber = function(s) {
var n = 0;
var len = s.length;
for(var i=s.length-1;i>=0;i--) {
n+=(s.charCodeAt(i)-64)*Math.pow(26,len-i-1);
}
return n;
};

Submission Detail

  • 1000 / 1000 test cases passed.
  • Your runtime beats 99.02 % of javascript submissions.

LeetCode - Algorithms - 371. Sum of Two Integers

这题不Easy呀,像智力题,像脑筋急转弯。
代码是人家的,我可想不出来。真是“会者不难,难者不会”。

JavaScript

自增自减运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @param {number} a
* @param {number} b
* @return {number}
*/
var getSum = function(a, b) {
if (a>0) {
while(a>0) {
a--;
b++
}
}
if (a<0) {
while(a<0) {
a++;
b--;
}
}
return b;
};

Submission Detail

  • 13 / 13 test cases passed.
  • Your runtime beats 3.38 % of javascript submissions.

位运算+递归

1
2
3
4
5
6
7
8
9
10
11
12
/**
* @param {number} a
* @param {number} b
* @return {number}
*/
var getSum = function(a, b) {
var sum,carry;
if (b==0) return a;
sum = a^b;
carry = (a&b)<<1;
return getSum(sum,carry);
};

Submission Detail

  • 13 / 13 test cases passed.
  • Your runtime beats 69.57 % of javascript submissions

消除递归的位运算

知其然而不知其所以然,居然可以这么做,觉得很神奇

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* @param {number} a
* @param {number} b
* @return {number}
*/
var getSum = function(a, b) {
while(b!=0) {
var carry=a&b;
a = a^b;
b = carry<<1;
}
return a;
};

Submission Detail

  • 13 / 13 test cases passed.
  • Your runtime beats 100.00 % of javascript submissions.

Java

消除递归的位运算

1
2
3
4
5
6
7
8
9
10
class Solution {
public int getSum(int a, int b) {
while (b!=0) {
int carry = a&b;
a = a^b;
b = carry<<1;
}
return a;
}
}

Submission Detail

  • 13 / 13 test cases passed.
  • Your runtime beats 100.00 % of java submissions.

递归+位运算

1
2
3
4
5
6
7
8
9
class Solution {
public int getSum(int a, int b) {
int sum,carry;
if (b==0) return a;
sum = a ^ b;
carry = (a & b) << 1;
return getSum(sum,carry);
}
}

Submission Detail

  • 13 / 13 test cases passed.
  • Your runtime beats 100.00 % of java submissions.

自增自减运算符

这个解很像脑筋急转弯,不难,但让人想不到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int getSum(int a, int b) {
if (a>0) {
while(a>0) {
a--;
b++;
}
}
if (a<0) {
while(a<0) {
a++;
b--;
}
}
return b;
}
}

Submission Detail

  • 13 / 13 test cases passed.
  • Your runtime beats 3.44 % of java submissions.