LeetCode 348 - Design Tic-Tac-Toe


http://www.cnblogs.com/grandyang/p/5467118.html
Design a Tic-tac-toe game that is played between two players on a n x n grid.
You may assume the following rules:
A move is guaranteed to be valid and is placed on an empty block.
Once a winning condition is reached, no more moves is allowed.
A player who succeeds in placing n of their marks in a horizontal, vertical, or diagonal row wins the game.
Example:
Given n = 3, assume that player 1 is "X" and player 2 is "O" in the board.
TicTacToe toe = new TicTacToe(3);
toe.move(0, 0, 1); -> Returns 0 (no one wins)
|X| | |
| | | | // Player 1 makes a move at (0, 0).
| | | |
toe.move(0, 2, 2); -> Returns 0 (no one wins)
|X| |O|
| | | | // Player 2 makes a move at (0, 2).
| | | |
toe.move(2, 2, 1); -> Returns 0 (no one wins)
|X| |O|
| | | | // Player 1 makes a move at (2, 2).
| | |X|
toe.move(1, 1, 2); -> Returns 0 (no one wins)
|X| |O|
| |O| | // Player 2 makes a move at (1, 1).
| | |X|
toe.move(2, 0, 1); -> Returns 0 (no one wins)
|X| |O|
| |O| | // Player 1 makes a move at (2, 0).
|X| |X|
toe.move(1, 0, 2); -> Returns 0 (no one wins)
|X| |O|
|O|O| | // Player 2 makes a move at (1, 0).
|X| |X|
toe.move(2, 1, 1); -> Returns 1 (player 1 wins)
|X| |O|
|O|O| | // Player 1 makes a move at (2, 1).
|X|X|X|
Follow up:
Could you do better than O(n2) per move() operation?
Hint:
Could you trade extra space such that move() operation can be done in O(1)?
You need two arrays: int rows[n], int cols[n], plus two variables: diagonal, anti_diagonal.


Follow up中让我们用更高效的方法,那么根据提示中的,我们建立一个大小为n的一维数组rows和cols,还有变量对角线diag和逆对角线rev_diag,这种方法的思路是,如果玩家1在第一行某一列放了一个子,那么rows[0]自增1,如果玩家2在第一行某一列放了一个子,则rows[0]自减1,那么只有当rows[0]等于n或者-n的时候,表示第一行的子都是tne一个玩家放的,则游戏结束返回该玩家即可,其他各行各列,对角线和逆对角线都是这种思路,参见代码如下:
https://leetcode.com/discuss/101219/7-8-lines-o-1-java-python

public class TicTacToe {

    public TicTacToe(int n) {
        count = new int[6*n][3];
    }

    public int move(int row, int col, int player) {
        int n = count.length / 6;
        for (int x : new int[]{row, n+col, 2*n+row+col, 5*n+row-col})
            if (++count[x][player] == n)
                return player;
        return 0;
    }

    int[][] count;
}
https://leetcode.com/discuss/101144/java-o-1-solution-easy-to-understand
In the previous solution, we allocate two arrays for player 1 and 2, respectively. Actually we can use only one array for both of the players. Say, if it is player 1 put one chess, add that location by 1. If it is player 2, deduce it by one. Finally, if either player 1 or player 2 win, that location must be equal to n or -n. 

The key observation is that in order to win Tic-Tac-Toe you must have the entire row or column. Thus, we don't need to keep track of an entire n^2 board. We only need to keep a count for each row and column. If at any time a row or column matches the size of the board then that player has won.
To keep track of which player, I add one for Player1 and -1 for Player2. There are two additional variables to keep track of the count of the diagonals. Each time a player places a piece we just need to check the count of that row, column, diagonal and anti-diagonal.
private int[] rows; private int[] cols; private int diagonal; private int antiDiagonal; /** Initialize your data structure here. */ public TicTacToe(int n) { rows = new int[n]; cols = new int[n]; } /** Player {player} makes a move at ({row}, {col}). @param row The row of the board. @param col The column of the board. @param player The player, can be either 1 or 2. @return The current winning condition, can be either: 0: No one wins. 1: Player 1 wins. 2: Player 2 wins. */ public int move(int row, int col, int player) { int toAdd = player == 1 ? 1 : -1; rows[row] += toAdd; cols[col] += toAdd; if (row == col) { diagonal += toAdd; } if (col == (cols.length - row - 1)) { antiDiagonal += toAdd; } int size = rows.length; if (Math.abs(rows[row]) == size || Math.abs(cols[col]) == size || Math.abs(diagonal) == size || Math.abs(antiDiagonal) == size) { return player; } return 0; }
https://leetcode.com/discuss/101143/13-lines-simple-and-clean-o-1-java-solution
int[] rows, cols; int n, diagonal = 0, antiDiagonal = 0; public TicTacToe(int n) { this.n = n; rows = new int[n]; cols = new int[n]; } public int move(int row, int col, int player) { if(player == 1){ if(++rows[row] == n || ++cols[col] == n) return 1; if(row == col && ++diagonal == n) return 1; if(row + col == n - 1 && ++antiDiagonal == n) return 1; }else{ if(--rows[row] == -n || --cols[col] == -n) return 2; if(row == col && --diagonal == -n) return 2; if(row + col == n - 1 && --antiDiagonal == -n) return 2; } return 0; }

http://buttercola.blogspot.com/2016/06/leetcode-348-design-tic-tac-toe.html
public class TicTacToe {
    private int[][] rows;
    private int[][] cols;
    private int[] diag;
    private int[] xdiag;
    private int n;
    /** Initialize your data structure here. */
    public TicTacToe(int n) {
        this.n = n;
        rows = new int[2][n];
        cols = new int[2][n];
        diag = new int[2];
        xdiag = new int[2];
    }
     
    /** Player {player} makes a move at ({row}, {col}).
        @param row The row of the board.
        @param col The column of the board.
        @param player The player, can be either 1 or 2.
        @return The current winning condition, can be either:
                0: No one wins.
                1: Player 1 wins.
                2: Player 2 wins. */
    public int move(int row, int col, int player) {
        int p = player == 1 ? 0 : 1;
         
        rows[p][row]++;
        cols[p][col]++;
         
        if (row == col) {
            diag[p]++;
        }
             
        // X-diagonal
        if (row + col == n - 1) {
            xdiag[p]++;
        }
             
        // If any of them equals to n, return 1
        if (rows[p][row] == n || cols[p][col] == n ||
            diag[p] == n || xdiag[p] == n) {
            return p + 1;
        }
         
        return 0;
    }
}

Not good - just different
http://dartmooryao.blogspot.com/2016/05/leetcode-348-design-tic-tac-toe.html
    Map<String, Integer> map;
    int n;

    /** Initialize your data structure here. */
    public TicTacToe(int n) {
        this.n = n;
        this.map = new HashMap<>();
    }
   
    /** Player {player} makes a move at ({row}, {col}).
        @param row The row of the board.
        @param col The column of the board.
        @param player The player, can be either 1 or 2.
        @return The current winning condition, can be either:
                0: No one wins.
                1: Player 1 wins.
                2: Player 2 wins. */
    public int move(int row, int col, int player) {
        String rowKey = "R"+row+"_"+player;
        int countR = map.getOrDefault(rowKey, 0)+1;
        map.put(rowKey, countR);
       
        String colKey = "C"+col+"_"+player;
        int countC = map.getOrDefault(colKey, 0)+1;
        map.put(colKey, countC);
       
        int countD1 = 0;
        if(row == col){
            String d1Key = "D1_"+player;
            countD1 = map.getOrDefault(d1Key, 0)+1;
            map.put(d1Key, countD1);
        }
       
        int countD2 = 0;
        if(row + col == n-1){
            String d2Key = "D2_"+player;
            countD2 = map.getOrDefault(d2Key, 0)+1;
            map.put(d2Key, countD2);
        }

        if(countR == n || countC == n || countD1 == n || countD2 == n){
            return player;
        }else{
            return 0;
        }
    }

O(n2)的解法,这种方法的思路很straightforward,就是建立一个nxn大小的board,其中0表示该位置没有棋子,1表示玩家1放的子,2表示玩家2。那么棋盘上每增加一个子,我们都每行每列,对角线和逆对角线来扫描一遍棋盘,看看是否有三子相连的情况,有的话则返回对应的玩家,没有则返回0
    TicTacToe(int n) {
        board.resize(n, vector<int>(n, 0));   
    }

    int move(int row, int col, int player) {
        board[row][col] = player;
        int i = 0, j = 0, N = board.size();
        for (i = 0; i < N; ++i) {
            if (board[i][0] != 0) {
                for (j = 1; j < N; ++j) {
                    if (board[i][j] != board[i][j - 1]) break;
                }
                if (j == N) return board[i][0];
            }
        }
        for (j = 0; j < N; ++j) {
            if (board[0][j] != 0) {
                for (i = 1; i < N; ++i) {
                    if (board[i][j] != board[i - 1][j]) break;
                }
                if (i == N) return board[0][j];
            }
        }
        if (board[0][0] != 0) {
            for (i = 1; i < N; ++i) {
                if (board[i][i] != board[i - 1][i - 1]) break;
            }
            if (i == N) return board[0][0];
        }
        if (board[N - 1][0] != 0) {
            for (i = 1; i < N; ++i) {
                if (board[N - i - 1][i] != board[N - i][i - 1]) break;
            }
            if (i == N) return board[N - 1][0];
        }
        return 0;
    }
    vector<vector<int>> board;
http://stackoverflow.com/questions/22087006/using-arrays-to-detect-a-win-in-a-gomoku-game
https://github.com/javierchavez/Gomoku/blob/master/Gomoku.java

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