Skip to content

Commit 1585876

Browse files
committed
tic-tac-toe game, trapping the water
1 parent b3fda35 commit 1585876

File tree

3 files changed

+138
-18
lines changed

3 files changed

+138
-18
lines changed

src/main/java/joshua/leetcode/array/twopointers/TrappingRainWater.java

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import joshua.leetcode.solutiontag.Stacks;
44
import joshua.leetcode.solutiontag.TwoPointers;
5-
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
65

76
import java.util.Deque;
87
import java.util.LinkedList;
@@ -20,21 +19,61 @@ public abstract class TrappingRainWater {
2019
* <p/>
2120
* compute how much water it is able to trap after raining.
2221
* <p/>
23-
*
22+
* <p/>
2423
* For example,
2524
* Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.
2625
*
27-
* @param height
26+
* @param height the array of heights.
2827
* @return
2928
*/
3029
public abstract int trap(int[] height);
3130

3231
@TwoPointers
3332
public static class Solution1 extends TrappingRainWater {
3433

34+
/**
35+
* 双指针法的思路解释如下:
36+
* left pointer和right pointer从两端向中间移动,肯定有一侧高,一侧低。这时候从低的一侧灌水肯定能trap住。
37+
* 因此可以继续移动低的一侧的指针,同时判断移动的过程中能够trap的水量(小方块),直到到达最低点。
38+
* 这时候再次判断left pointer和right pointer的大小。
39+
* 直到两个指针相遇。
40+
*/
3541
@Override
3642
public int trap(int[] height) {
37-
throw new NotImplementedException();
43+
// can only trap water when length >= 3
44+
if (height == null || height.length < 3) {
45+
return 0;
46+
}
47+
int water = 0;
48+
int leftPointer = 0;
49+
int rightPointer = height.length - 1;
50+
int maxLeft = 0;
51+
int maxRight = 0;
52+
// 结束条件
53+
while (leftPointer < rightPointer) {
54+
// 左低右高,计算左侧蓄水量
55+
if (height[leftPointer] < height[rightPointer]) {
56+
// 无法继续蓄水,更新左侧Bar值
57+
if (maxLeft < height[leftPointer]) {
58+
maxLeft = height[leftPointer];
59+
} else {
60+
// 蓄水量
61+
water += maxLeft - height[leftPointer];
62+
}
63+
leftPointer++;
64+
} else {
65+
// 左高右低,计算右侧需水量
66+
if (maxRight < height[rightPointer]) {
67+
// 无法继续蓄水,更新右侧Bar值
68+
maxRight = height[rightPointer];
69+
} else {
70+
// 蓄水量
71+
water += maxRight - height[rightPointer];
72+
}
73+
rightPointer--;
74+
}
75+
}
76+
return water;
3877
}
3978
}
4079

@@ -53,23 +92,18 @@ public int trap(int[] height) {
5392
Deque<Integer> stack = new LinkedList<Integer>();
5493
// stack stores the index of element.
5594
int water = 0;
56-
stack.push(0);
57-
for (int i = 1; i < height.length; i++) {
58-
if(stack.isEmpty() || height[i] < height[stack.peek()]) {
95+
for (int i = 0; i < height.length; i++) {
96+
if (stack.isEmpty() || height[stack.peek()] >= height[i]) {
5997
stack.push(i);
60-
continue;
61-
}
62-
int bottom = height[stack.pop()];
63-
while (!stack.isEmpty()) {
64-
if ( height[stack.peek()] <= height[i]) {
65-
int idx = stack.pop();
66-
water += (i - idx - 1) * (height[idx] - bottom);
67-
bottom = height[idx];
68-
} else {
69-
break;
98+
} else {
99+
int tmp = stack.pop();
100+
if (!stack.isEmpty()) {
101+
int heightVal = Math.min(height[stack.peek()], height[i]) - height[tmp];
102+
int widthVal = i - stack.peek() - 1;
103+
water += heightVal * widthVal;
70104
}
105+
i--;
71106
}
72-
stack.push(i);
73107
}
74108
return water;
75109
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package joshua.leetcode.design;
2+
3+
/**
4+
* 348. Design Tic-Tac-Toe <br/>
5+
* <p/>
6+
* <a href = "https://leetcode.com/problems/design-tic-tac-toe/">leetcode link</a>
7+
* <p/>
8+
* Created by joshu on 2016/5/26.
9+
*/
10+
public abstract class TicTacToe {
11+
12+
/**
13+
* Initialize your data structure here.
14+
*
15+
* @param n the length of column and row.
16+
*/
17+
public TicTacToe(int n) {
18+
}
19+
20+
/**
21+
* Player {player} makes a move at ({row}, {col}).
22+
*
23+
* @param row The row of the board.
24+
* @param col The column of the board.
25+
* @param player The player, can be either 1 or 2.
26+
* @return The current winning condition, can be either:
27+
* 0: No one wins.
28+
* 1: Player 1 wins.
29+
* 2: Player 2 wins.
30+
*/
31+
public abstract int move(int row, int col, int player);
32+
33+
public static class Solution1 extends TicTacToe {
34+
35+
int[] rows;
36+
int[] columns;
37+
int n;
38+
int diagonal;
39+
int antiDiagonal;
40+
41+
public Solution1(int n) {
42+
super(n);
43+
rows = new int[n];
44+
columns = new int[n];
45+
this.n = n;
46+
}
47+
48+
/**
49+
* X 表示 play 1. player 1赢棋。
50+
* |X| |O|
51+
* |O|O| |
52+
* |X|X|X|
53+
*
54+
* 如果用 col[3]和row[3]表示每个点在两个轴的投影,可以得出结论最后一行全是X,所以row[2] == 3。
55+
* 因此可以用两个数组记录每次下棋在两个轴上的投影,X表示-1, O表示1.任意一个轴上某个位置的值等于3或者-3
56+
* 就表示当前棋手赢了。
57+
* 另外需要两个变量保存对角线和斜对角线上的值得累加。
58+
*
59+
*/
60+
@Override
61+
public int move(int row, int col, int player) {
62+
int val = player == 1 ? 1 : -1;
63+
rows[row] += val;
64+
if (rows[row] == n * val) return player;
65+
columns[col] += val;
66+
if (columns[col] == n * val) return player;
67+
if (row == col) {
68+
diagonal += val;
69+
if (diagonal == n * val) return player;
70+
}
71+
if (row + col == n - 1) {
72+
antiDiagonal += val;
73+
if (antiDiagonal == n * val) return player;
74+
}
75+
return 0;
76+
}
77+
}
78+
}

src/test/java/joshua/leetcode/array/twopointers/TrappingRainWaterTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,12 @@ public void testSolution2() {
2525
}
2626
}
2727

28+
@Test
29+
public void testSolution1() {
30+
TrappingRainWater sol=new TrappingRainWater.Solution1();
31+
for (int[] key : cases.keySet()) {
32+
assertEquals((int)cases.get(key), sol.trap(key));
33+
}
34+
}
35+
2836
}

0 commit comments

Comments
 (0)