2015-11-20 20 views
7

Trong một cuộc phỏng vấn kỹ thuật 45 phút với Google, tôi đã được hỏi một vấn đề về đồ thị Leaper. Tôi đã viết mã làm việc, nhưng sau đó đã bị từ chối lời mời làm việc vì tôi thiếu kiến ​​thức về cấu trúc dữ liệu. Tôi tự hỏi những gì tôi có thể làm tốt hơn.Thuật toán tối ưu hóa đồ thị Leaper?

Vấn đề là như sau: "Cho một bảng có kích thước N, và nói rằng một mảnh có thể nhảy tôi vị trí theo chiều ngang (trái hoặc phải) và j vị trí theo chiều dọc (lên hoặc xuống) (Tức là, giống như một con ngựa trong cờ vua), người chơi có thể tiếp cận mọi vị trí trên bảng không? "

Tôi đã viết thuật toán sau. Nó đệ quy tìm hiểu xem mọi vị trí trên bảng có thể truy cập được bằng cách đánh dấu tất cả các điểm trên biểu đồ đã được truy cập hay không. Nếu nó không thể truy cập được, thì ít nhất một trường sai và hàm sẽ trả về false.

 static boolean reachable(int i, int j, int n) { 
     boolean grid[][] = new boolean[n][n]; 
     reachableHelper(0, 0, grid, i, j, n - 1); 
     for (int x = 0; x < n; x++) { 
      for (int y = 0; y < n; y++) { 
      if (!grid[x][y]) { 
       return false; 
      } 
      } 
     } 
     return true; 
     } 

     static void reachableHelper(int x, int y, boolean[][] grid, int i, int j, int max) { 
     if (x > max || y > max || x < 0 || y < 0 || grid[x][y]) { 
      return; 
     } 
     grid[x][y] = true; 
     int i2 = i; 
     int j2 = j; 
     for (int a = 0; a < 2; a++) { 
      for (int b = 0; b < 2; b++) { 
      reachableHelper(x + i2, y + j2, grid, i, j, max); 
      reachableHelper(x + j2, y + i2, grid, i, j, max); 
      i2 = -i2; 
      } 
      j2 = -j2; 
     } 
     } 

Bây giờ, sau đó được chỉ ra rằng giải pháp tối ưu sẽ được thực hiện Donald Knuth đồng thủ thực hiện: http://arxiv.org/pdf/math/9411240v1.pdf Liệu đó có phải ta nên có thể hình dung ra trên một cuộc phỏng vấn kỹ thuật 45 phút? ?

Bên cạnh đó, có bất kỳ điều gì tôi có thể làm tốt hơn không?

chỉnh sửa:
- Tôi hỏi về vị trí bắt đầu. Tôi đã nói bắt đầu từ 0,0 là tốt.

edit2 Dựa trên phản hồi, tôi đã viết một vòng lặp while với phương thức xếp hàng. Cách tiếp cận đệ quy chạy vào tràn ngăn xếp khi n = 85. Tuy nhiên, vòng lặp while với phương thức xếp hàng bên dưới hoạt động tối đa ~ n = 30.000. (sau đó nó chạy vào đống vấn đề với bộ nhớ vượt quá GB). Nếu bạn biết cách tối ưu hóa thêm, vui lòng cho tôi biết.

static boolean isReachableLoop(int i, int j, int n) { 
     boolean [][] grid = new boolean [n][n]; 

     LinkedList<Point> queue = new LinkedList<Point>(); 
     queue.add(new Point(0,0)); // starting position. 

     int nodesVisited = 0; 
     while (queue.size() != 0) { 
      Point pos = queue.removeFirst(); 

      if (pos.x >= 0 && pos.y >= 0 && pos.x < n && pos.y < n) { 
      if (!grid[pos.x][pos.y]) { 
       grid[pos.x][pos.y] = true; 
       nodesVisited++; 
       int i2 = i; 
       int j2 = j; 
       for (int a = 0; a < 2; a++) { 
       for (int b = 0; b < 2; b++) { 
        queue.add(new Point(pos.x+i2, pos.y+j2)); 
        queue.add(new Point(pos.x+j2, pos.y+i2)); 
        i2 = -i2; 
       } 
       j2 = -j2; 
       } 
      } 
      } 
     } 
     if (nodesVisited == (n * n)) { 
      return true; 
     } else { 
      return false; 
     } 
     } 
+1

Bạn có được vị trí bắt đầu không? Hay bạn phải tự khám phá vị trí tối ưu? – smac89

+1

Tôi hỏi người phỏng vấn về điều đó. Tôi được cho biết 0x0 là một vị trí hợp pháp. –

+3

Nếu bạn có thể tiếp cận mọi nơi trên bảng từ vị trí * any *, bạn có thể tiếp cận mọi nơi trên bảng từ vị trí * mọi *, vì vậy vị trí bắt đầu không quan trọng –

Trả lời

3

Tôi hỏi rất nhiều câu hỏi phỏng vấn như thế này. Tôi không nghĩ rằng bạn sẽ được dự kiến ​​sẽ tìm ra phương pháp coprime trong cuộc phỏng vấn, nhưng tôi đã cập bến bạn để sử dụng không gian ngăn xếp O (n^2) - đặc biệt là khi bạn chuyển tất cả các tham số đó cho mỗi cuộc gọi đệ quy thay vì sử dụng một đối tượng.

Tôi đã hỏi bạn về điều đó và dự kiến ​​bạn sẽ tìm ra BFS hoặc DFS bằng cách sử dụng ngăn xếp hoặc hàng đợi trên heap. Nếu bạn thất bại về điều đó, tôi có thể có một khiếu nại như "thiếu kiến ​​thức cấu trúc dữ liệu".

Tôi cũng đã đặt câu hỏi để đảm bảo bạn biết mình đang làm gì khi phân bổ mảng 2D đó.

Nếu bạn thực sự tốt, tôi sẽ hỏi bạn liệu bạn có thể sử dụng tính đối xứng của vấn đề để giảm không gian tìm kiếm của bạn không. Bạn thực sự chỉ phải tìm kiếm một mạng lưới có kích thước J * J (giả sử J> = i).

Điều quan trọng cần nhớ là người phỏng vấn không chỉ xem xét câu trả lời của bạn. Anh ấy đang nhìn vào cách bạn giải quyết vấn đề và những công cụ bạn có trong bộ não của bạn mà bạn có thể mang đến để giải quyết vấn đề.

Chỉnh sửa: suy nghĩ về điều này một số chi tiết, có rất nhiều bước gia tăng trên đường đến phương pháp đồng nhất mà bạn cũng có thể đưa ra. Không ai mong đợi điều đó, nhưng nó sẽ rất ấn tượng!

+1

Tôi hiểu. Cảm ơn bạn đã phản hồi. –

+0

Tôi đã thêm một phương pháp tiếp cận hàng đợi trong vòng lặp +. (xem chỉnh sửa 2). Bạn có chấp nhận mã như vậy không? –

+1

Nó không có bất kỳ vấn đề nghiêm trọng. ArrayDeque cho BFS hoặc ArrayList cho DFS hiệu quả hơn LinkedList và bạn sẽ sử dụng ít hơn 80% bộ nhớ nếu bạn đã kiểm tra lưới [] [] trước khi đặt các điểm vào hàng đợi. –

2

Tôi rất tiếc, tôi cảm thấy mình đang thiếu thứ gì đó.

Nếu bạn chỉ có thể đi lên hoặc xuống bằng i và trái hoặc phải bằng j, thì trường hợp (x, y) có thể truy cập từ trường hợp bắt đầu (a, b) nếu có số nguyên m và n sao cho

a + m * i = x

b + n * j = y

Đó là, tất cả mọi thứ là sai cho một bảng vuông trong đó n> 1.

Nếu bạn có nghĩa là giống như một hiệp sĩ trong c hess, và bạn có thể đi lên/xuống bởi tôi và trái/phải bởi j HOẶC lên/xuống bởi j và trái/phải bởi tôi, bạn có thể sử dụng cùng một kỹ thuật. Nó chỉ trở thành 2 phương trình để giải quyết:

một + m * i + n * j = x

b + o * i + p * j = y

Nếu không có các số nguyên m, n, o và p thỏa mãn các phương trình đó, bạn không thể đạt tới điểm đó.

+0

Sau này, giống như một hiệp sĩ có thể nhảy đến 8 vị trí khác nhau. Câu hỏi không phải là về việc đạt x, y, nhưng nếu mọi điểm trên bảng đều có thể liên lạc với bạn. Ngoài ra, trong trường hợp của tôi, tôi đã phải viết mã cụ thể hơn là viết một phương trình toán học? (Suy nghĩ?) –

+0

Nếu bạn có thể kiểm tra xem một điểm có thể đạt được hay không, bạn chỉ phải lặp lại từng điểm và thực hiện kiểm tra mỗi lần. Có một số tối ưu hóa nhiều hơn hoặc ít rõ ràng hơn có thể được thêm vào như sử dụng đối xứng của vấn đề để giảm không gian tìm kiếm. – Leherenn

+0

Thực tế là bảng chỉ có chiều rộng hữu hạn đặt một điều kiện khác trên các số nguyên m và n của bạn (và o và p). Và trong trường hợp thứ hai ("giống hiệp sĩ"), cũng có những ràng buộc m = p và n = o. –

Các vấn đề liên quan