tic-tac-toe Who Won - Cracking the coding interview--Q19.2


Cracking the coding interview--Q19.2
Design an algorithm to figure out if someone has won in a game of tic-tac-toe.
设计算法检查某人是否赢得了井字游戏。

Tic-tac-toe (also known as Noughts and crosses or Xs and Os) is a paper-and-pencil game for two players, X and O, who take turns marking the spaces in a 3×3 grid. The player who succeeds in placing three of their marks in a horizontal, vertical, or diagonal row wins the game.

假设这个检查某人是否赢得了井字游戏的函数为HasWon,那么我们第一步要向面试官确认, 这个函数是只调用一次,还是要多次频繁调用。如果是多次调用, 我们可以通过预处理来得到一个非常快速的版本。

方法一:如果HasWon函数需要被频繁调用对于井字游戏,每个格子可以是空,我的棋子和对方的棋子3种可能,总共有39 = 19683 种可能状态。我们可以把每一种状态转换成一个整数, 预处理时把这个状态下是否有人赢得了井字游戏保存起来,每次检索时就只需要O(1)时间。 比如每个格子上的3种状态为0(空),1(我方棋子),2(对方棋子),棋盘从左到右, 从上到下依次记为0到8,那么任何一个状态都可以写成一个3进制的数,再转成10进制即可。 比如,下面的状态:


 // 方法一:如果HasWon函数需要被频繁调用
 public static int convertBoardToInt(char[][] board) {
        int factor = 1;
        int sum = 0;
        for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board[i].length; j++) {
                        int v = 0;
                        switch(board[i][j]){
                         case 'x':
                          v = 1;
                          break;
                         case 'o':
                          v = 2;
                          break;
                         default:
                          v = 0;
                        }
                        
                        sum += v * factor;
                        factor *= 3;
                }
        }
        return sum;
 }
方法二:如果HasWon函数只被调用一次或很少次
http://blog.csdn.net/fightforyourdream/article/details/17066247
https://github.com/yxjiang/algorithms/blob/master/src/main/java/algorithm/cc150/chapter17/Question2.java

public boolean won(char[][] board) { // write implementation here
if (checkDiagonal(board) || checkCounterDiagonal(board)) {
return true;
}
for (int i = 0; i < board.length; ++i) {
if (checkRow(i, board) || checkCol(i, board)) {
return true;
}
}
return false;
}
private boolean checkRow(int row, char[][] board) {
for (int i = 0; i < board.length - 1; ++i) {
if (board[row][i] != board[row][i + 1]) {
return false;
}
}
if (board[row][0] != '.') {
return true;
}
return false;
}
private boolean checkCol(int col, char[][] board) {
for (int i = 0; i < board.length - 1; ++i) {
if (board[i][col] != board[i + 1][col]) {
return false;
}
}
if (board[0][col] != '.') {
return true;
}
return false;
}
private boolean checkDiagonal(char[][] board) {
char type = board[0][0];
for (int i = 1; i < board.length; ++i) {
if (board[i][i] != type) {
return false;
}
}
if (type != '.') {
return true;
}
return false;
}
private boolean checkCounterDiagonal(char[][] board) {
char type = board[board.length - 1][0];
for (int i = 1; i < board.length; ++i) {
if (board[i][board.length - 1 - i] != type) {
return false;
}
}
if (type != '.') {
return true;
}
return false;
}

1. Will has Won be called just once or many times (for instance, as part of a tic-tac-toe website)? If the latter is the case, we may want to add pre-processing time to optimize the runtime of ha sWon.
2. Do we know the last move that was made?
3. Tic-tac-toe is usually on a 3x3 board. Do we want to design for just that, or do we want to implement it as an NxN solution?

There are only 39, or about 20,000, tic-tac-toe boards (assuming a 3x3 board). Therefore, we can represent our tic-tac-toe board as an int, with each digit representing a piece (0 means Empty, 1 means Red, 2 means Blue). We set up a hash table or array in advance with all possible boards as keys and the value indicating who has won.

Piece hasWon(int board) {
        return winnerHashtable[board];
}
enum Piece { Empty, Red, Blue};

int convertBoardToint(Piece[][] board) {
        int sum = 0;
        for (int i= 0; i < board.length; i++) {
                for (int j = 0; j < board[i].length; j++) {
                        /* Each value in enum has an integer associated with it. We
                         * can just use that. */
                        int value = board[i][j].ordinal();
                        sum = sum * 3 + value;
                }
        }
        return sum;
}
Solution #2: If we know the last move
If we know the very last move that was made (and we've been checking for a winner up until now), then we only need to check the row, column, and diagonal that overlaps with this position.
Piece hasWon(Piece[][] board, int row, int column) {
        if (board.length != board[0].length) return Piece.Empty;

        Piece piece = board[row][column];
        if (piece == Piece.Empty) return Piece.Empty;

        if (hasWonRow(board, row) I I hasWonColumn(board, column)) {
                return piece;
        }

        if (row == column && haswonDiagonal(board, 1)) {
                return piece;
        }

        if (row == (board.length - column - 1) && hasWonDiagonal(board, -1)) {
                return piece;
        }
        return Piece.Empty;
}

boolean hasWonRow(Piece[][] board, int row) {
        for (int c = 1; c < board[row].length; c++) {
                if (board[row][c] != board[row][0]) {
                        return false;
                }
        }
        return true;
}

boolean hasWonColumn(Piece[][] board, int column) {
        for (int r = 1; r < board.length; r++) {
                if (board[r][column] != board[0][column]) {
                        return false;
                }
        }
        return true;
}

boolean hasWonDiagonal(Piece[][] board, int direction) {
        int row = 0;
        int column = direction == 1 ? 0 : board.length - 1;
        Piece first= board[0][column];
        for (int i= 0; i < board.length; i++) {
                if (board[row][column] != first) {
                        return false;
                }
                row += 1;
                column += direction;
        }
        return true;
}


Solution #3: Designing for just a 3x3 board
Piece hasWon(Piece[][] board) {
        for (int i= 0; i < board.length; i++) {
                /* Check Rows */
                if (hasWinner(board[i][0], board[i][l], board[i][2])) {
                        return board[i][0];

                }

                /* Check Columns */
                if (hasWinner(board[0][i], board[l][i], board[2][i])) {
                        return board[0][i];
                }
        }
        if (hasWinner(board[0][0], board[l][l], board[2][2])) {
                return board[0][0];
        }

        if (hasWinner(board[0][2], board[l][l], board[2][0])) {
                return board[0][2];
        }

        return Piece.Empty;
}

boolean hasWinner(Piece pl, Piece p2, Piece p3) {
        if (pl == Piece.Empty) {
                return false;
        }
        return pl== p2 && p2 == p3;
}
Solution #4: Designing for an NxN board
Read full article from Cracking the coding interview--Q19.2

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts