LeetCode-找出井字棋的获胜者

我的解答

  1. 先分组
  2. 然后再判断每组是否存在成功连线的情况
public class Main {

	public static void main(String[] args) throws Exception {
	int[][] moves=new int[][]{{0,0}, {1,1},{2,0},{1,0},{1,2},{2,1},{0,1},{0,2},{2,2}};

	System.out.println(tictactoe(moves));

	}
	public static String tictactoe(int[][] moves) {
		List<int[]> listA=new ArrayList<>();
		List<int[]> listB=new ArrayList<>();
		for(int i=0;i<moves.length;i++){
			if(i%2==0){
				listA.add(moves[i]);
			}
			else{
				listB.add(moves[i]);
			}
		}
		if(hasThree(listA)){
			return "A";
		}
		if(hasThree(listB)){
			return "B";
		}
		if(moves.length<9){
			return "Pending";
		}
		return "Draw";
	}
	private static boolean isEqual(int[] old,int[] _new){
		return Arrays.equals(old,_new);
	}
	private static boolean hasThree(List<int[]> moves){
		int _one=0,_two=0,_three=0,_four=0,_five=0,_six=0,_seven=0,_eight=0;
		for(int i=0;i<moves.size();i++){
			if(Arrays.equals(moves.get(i), new int[]{0, 0}) ||Arrays.equals(moves.get(i),new int[]{0,1})||Arrays.equals(moves.get(i),new int[]{0,2})){
				_one++;
			}
			if(Arrays.equals(moves.get(i),new int[]{1,0})||Arrays.equals(moves.get(i),new int[]{1,1})||Arrays.equals(moves.get(i),new int[]{1,2})){
				_two++;
			}
			if(Arrays.equals(moves.get(i),new int[]{2,0})||Arrays.equals(moves.get(i),new int[]{2,1})||Arrays.equals(moves.get(i),new int[]{2,2})){
				_three++;
			}
			if(Arrays.equals(moves.get(i),new int[]{0,0})||Arrays.equals(moves.get(i),new int[]{1,0})||Arrays.equals(moves.get(i),new int[]{2,0})){
				_four++;
			}
			if(Arrays.equals(moves.get(i),new int[]{0,1})||Arrays.equals(moves.get(i),new int[]{1,1})||Arrays.equals(moves.get(i),new int[]{2,1})){
				_five++;
			}
			if(Arrays.equals(moves.get(i),new int[]{0,2})||Arrays.equals(moves.get(i),new int[]{1,2})||Arrays.equals(moves.get(i),new int[]{2,2})){
				_six++;
			}
			if(Arrays.equals(moves.get(i),new int[]{0,0})||Arrays.equals(moves.get(i),new int[]{1,1})||Arrays.equals(moves.get(i),new int[]{2,2})){
				_seven++;
			}
			if(Arrays.equals(moves.get(i),new int[]{0,2})||Arrays.equals(moves.get(i),new int[]{1,1})||Arrays.equals(moves.get(i),new int[]{2,0})){
				_eight++;
			}

		}
		return _one>2||_two>2||_three>2||_four>2||_five>2||_six>2||_seven>2||_eight>2;
	}
}

AI的解答

import java.util.*;

public class Main {
    // 预定义所有胜利路径(8种可能)
    private static final int[][][] WIN_LINES = {
        {{0,0}, {0,1}, {0,2}}, // 第一行
        {{1,0}, {1,1}, {1,2}}, // 第二行
        {{2,0}, {2,1}, {2,2}}, // 第三行
        {{0,0}, {1,0}, {2,0}}, // 第一列
        {{0,1}, {1,1}, {2,1}}, // 第二列
        {{0,2}, {1,2}, {2,2}}, // 第三列
        {{0,0}, {1,1}, {2,2}}, // 主对角线
        {{0,2}, {1,1}, {2,0}}  // 副对角线
    };

    public static void main(String[] args) {
        int[][] moves = {{0,0}, {1,1}, {2,0}, {1,0}, {1,2}, {2,1}, {0,1}, {0,2}, {2,2}};
        System.out.println(tictactoe(moves));
    }

    public static String tictactoe(int[][] moves) {
        // 使用Set存储坐标提高查找效率
        Set<String> setA = new HashSet<>();
        Set<String> setB = new HashSet<>();
        
        for (int i = 0; i < moves.length; i++) {
            String pos = moves[i][0] + "," + moves[i][1];
            if (i % 2 == 0) setA.add(pos);
            else setB.add(pos);
        }
        
        if (checkWin(setA)) return "A";
        if (checkWin(setB)) return "B";
        return moves.length == 9 ? "Draw" : "Pending";
    }

    private static boolean checkWin(Set<String> moves) {
        // 检查所有胜利路径
        for (int[][] line : WIN_LINES) {
            int count = 0;
            for (int[] pos : line) {
                if (moves.contains(pos[0] + "," + pos[1])) {
                    count++;
                }
            }
            if (count == 3) return true; // 找到完整胜利路径
        }
        return false;
    }
}

思考

AI的解答和官方解答思路一致,它们的优点有:
1. 使用预定义的WIN_LINES常量清晰表示8种胜利路径
2. 用HashSet替代ArrayList存储落子位置,将查找复杂度从O(n)降至O(1)
3. 坐标存储为字符串(如"0,0")简化比较操作
4. 避免在每次胜利检查时创建新数组对象(原代码new int[]{0,0})

posted @ 2025-06-09 10:40  尼兰  阅读(9)  评论(0)    收藏  举报