劍指Offer面試題66:矩陣中的路徑 java實現

題目:矩陣中的路徑
          請設計一個函數,用來判斷在一個矩陣中是否存在一條包含某字符串所有字符的路徑。路徑可以從矩陣中任意一格開始,每一步可以在矩陣中向左右上下移動一格。如果一條路徑經過了矩陣的某一格,那麼該路徑不能再次進入該格子。例如,在下面的3x4的矩陣中包含一條字符串“bcced"的路徑。但該矩陣中不包含字符串"abcd",的路徑,因爲字符串的第一個字符b佔據了矩陣中的第一行第二個格子後,路徑不能再次進入這個格子。

a        b        c        e
s        f         c        s
a        d        e        e
算法分析:

        這是一個可以用回朔法解決的典型題。首先,在矩陣中任選一個格子作爲路徑的起點。假設矩陣中某個格子的字符爲ch,那麼這個格子不可能處在路徑上的第i個位置。如果路徑上的第i個字符不是ch,那麼這個格子不可能處在路徑上的第i個位置。如果路徑上的第i個字符正好是ch,那麼往相鄰的格子尋找路徑上的第i+1個字符。除在矩陣邊界上的格子之外,其他格子都有4個相鄰的格子。重複這個過程直到路徑上的所有字符都在矩陣中找到相應的位置。
  由於回朔法的遞歸特性,路徑可以被開成一個棧。當在矩陣中定位了路徑中前n個字符的位置之後,在與第n個字符對應的格子的周圍都沒有找到第n+1個字符,這個時候只要在路徑上回到第n-1個字符,重新定位第n個字符。
  由於路徑不能重複進入矩陣的格子,還需要定義和字符矩陣大小一樣的布爾值矩陣,用來標識路徑是否已經進入每個格子。
        當矩陣中座標爲(row,col)的格子和路徑字符串中下標爲pathLength的字符一樣時,從4個相鄰的格子(row,col-1),(row-1,col),(row,col+1)以及(row+1,col)中去定位路徑字符串中下標爲pathLength+1的字符。
  如果4個相鄰的格子都沒有匹配字符串中下標爲pathLength+1的字符,表明當前路徑字符串中下標爲pathLength的字符在矩陣中的定位不正確,我們需要回到前一個字符(pathLength-1),然後重新定位。
  一直重複這個過程,直到路徑字符串上所有字符都在矩陣中找到合適的位置


遇到問題:
        在nextInt(),next(),nextDouble(),nextFloat()方法與nextLine()連用並放在nextLine()前面時,就會出現如下錯誤:

            System.out.println("請輸入矩陣的行數:");
        int rows = scanner.nextInt();
        
        System.out.println("請輸入一個矩陣字符串,不包含空格:");
        String tmp = scanner.nextLine();
        
        System.out.println("請輸入矩陣的列數:");
        int cols = scanner.nextInt();
 
        System.out.println("請輸入要查詢的字符串:");
        String str = scanner.nextLine();
        scanner.close();  

        
         nextLine()並未讀取任何輸入,直接轉到了下一行。
    問題分析:
        nextLine()會把nextInt(),next(),nextDouble(),nextFloat()的結束換行符作爲字符串讀入,進而不需要從鍵盤輸入字符串nextLine便已經轉向了下一條語句執行。
    解決辦法:
        在每一個nextInt(),next(),nextDouble(),nextFloat()後都加一個nextLine()語句,將被next()去掉的Enter過濾掉。
代碼如下:
            System.out.println("請輸入矩陣的行數:");
        int rows = scanner.nextInt();
        scanner.nextLine();

        System.out.println("請輸入一個矩陣字符串,不包含空格:");
        String tmp = scanner.nextLine();
        
        System.out.println("請輸入矩陣的列數:");
        int cols = scanner.nextInt();
        scanner.nextLine();
        
        System.out.println("請輸入要查詢的字符串:");
        String str = scanner.nextLine();
        
        scanner.close();
        //SolutionMethod2 solution2 = new SolutionMethod2();
        System.out.println("矩陣中是否包含該字符串:");  

    運行結果:
        
 

算法源程序:
/**************************************************************      
* Copyright (c) 2016, 
* All rights reserved.                   
* 版 本 號:v1.0                   
* 題目描述:矩陣中的路徑
* 			請設計一個函數,用來判斷在一個矩陣中是否存在一條包含某字符串所有字符的路徑。路徑可以從矩陣中任意一格開始,
* 			每一步可以在矩陣中向左右上下移動一格。如果一條路徑經過了矩陣的某一格,那麼該路徑不能再次進入該格子。
* 			例如,在下面的3x4的矩陣中包含一條字符串“bcced"的路徑。但該矩陣中不包含字符串"abcd",的路徑,
* 			因爲字符串的第一個字符b佔據了矩陣中的第一行第二個格子後,路徑不能再次進入這個格子。
*			a        b        c        e
*			s        f        c        s
*			a        d        e        e
* 輸入描述:請輸入矩陣的行數:
*			3
*			請輸入矩陣的列數:
*			4
*			請輸入一個矩陣字符串,不包含空格:
*			abcesfcsadee
*			請輸入要查詢的字符串:
*			bcced
* 程序輸出:矩陣中是否包含該字符串:
*			true
* 問題分析: 1.  在nextInt(),next(),nextDouble(),nextFloat()方法與nextLine()連用並放在nextLine()前面時,
* 				會出現nextLine()輸入的字符串無法讀入便已轉換的下一行。
*        		原因:nextLine()會把nextInt(),next(),nextDouble(),nextFloat()的結束換行符作爲字符串讀入,
*        		進而不需要從鍵盤輸入字符串nextLine便已經轉向了下一條語句執行。
*    			解決辦法:在每一個nextInt(),next(),nextDouble(),nextFloat()後都加一個nextLine()語句,將被next()去掉的Enter過濾掉。	
* 算法描述: 這是一個可以用回朔法解決的典型題。首先,在矩陣中任選一個格子作爲路徑的起點。假設矩陣中某個格子的字符爲ch,
* 			那麼這個格子不可能處在路徑上的第i個位置。如果路徑上的第i個字符不是ch,那麼這個格子不可能處在路徑上的第i個位置。
* 			如果路徑上的第i個字符正好是ch,那麼往相鄰的格子尋找路徑上的第i+1個字符。除在矩陣邊界上的格子之外,
* 			其他格子都有4個相鄰的格子。重複這個過程直到路徑上的所有字符都在矩陣中找到相應的位置。
* 完成日期:2016-10-23
***************************************************************/

package org.marsguo.offerproject66;

import java.util.Scanner;

/*class SolutionMethod1{
	public boolean HasPathFunction(char[][]Matrix,String inputstr){
		if(Matrix == null || inputstr == null)
			return false;
		
		char[] strarray = inputstr.toCharArray();
		int rows = Matrix.length;		//矩陣行數
		int cols = Matrix[0].length;		//矩陣列數
		
		if(rows == 1 && cols ==1 && Matrix[rows][cols] != strarray[0])
			return false;
		
		int i = rows - 2;
		int j = cols - 2;
		for(int k = 0; k < strarray.length; k++){
			if(strarray[k] == Matrix[i][j]){
				i++;
			}
		}
	}
}*/

class SolutionMethod2{
	public boolean hasPath(char[] matrix,int rows,int cols,char[] str){
		int flag[] = new int[matrix.length];
		for(int i = 0; i < rows; i++){
			for(int j = 0; j < cols;j++){
				if(helper(matrix,rows,cols,i,j,str,0,flag))
					return true;
			}
		}
		return false;
	}
	
	public boolean helper(char[] matrix,int rows,int cols,int i,int j, char[] str,int k,int[] flag){
		int index = i * cols + j;
		if( i < 0 || i >= rows || j < 0 || j >= cols || matrix[index] != str[k] || flag[index] == 1)
			return false;
		if(k == str.length - 1)
			return true;
		flag[index] = 1;
		if(helper(matrix,rows,cols,i - 1,j, str,k + 1,flag)
				|| helper(matrix,rows,cols,i + 1,j,str,k + 1,flag)
				|| helper(matrix,rows,cols,i,j - 1,str,k + 1,flag)
				|| helper(matrix,rows,cols,i,j + 1,str,k + 1,flag)){
			return true;
		}
		flag[index] = 0;
		return false;
	}
}

public class HasPath {
	public static void main(String args[]){
		
		Scanner scanner = new Scanner(System.in);
		
		
		System.out.println("請輸入矩陣的行數:");
		int rows = scanner.nextInt();
		
		System.out.println("請輸入矩陣的列數:");
		int cols = scanner.nextInt();
		scanner.nextLine();
		
		System.out.println("請輸入一個矩陣字符串,不包含空格:");
		String tmp = scanner.nextLine();
		
		char[] arr = new char[tmp.length()];
		arr = tmp.toCharArray();
		
		System.out.println("請輸入要查詢的字符串:");
		String inputstr = scanner.nextLine();
		char[] strarray = new char[inputstr.length()];
		strarray = inputstr.toCharArray();
		
	/*	char[][] arrays = new char[rows][cols];
		
		for(int i = 0; i < rows; i++){
			for(int j = 0; j < cols; j++){
				
			}
		}*/
		scanner.close();

		SolutionMethod2 solution2 = new SolutionMethod2();
		System.out.println("矩陣中是否包含該字符串:");
		System.out.println(solution2.hasPath(arr, rows, cols, strarray));
	}
}


程序運行結果:




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章