最小操作數


給了A、B兩個單詞和一個單詞集合Dict,每個的長度都相同。我們希望通過若干次操作把單詞A變成單詞B,每次操作可以改變單詞中的一個字母,同時,新產生的單詞必須是在給定的單詞集合Dict中。求所有行得通步數最少的修改方法。    


舉個例子如下: Given:    A = "hit"    B = "cog"    Dict = ["hot","dot","dog","lot","log"] 

Return  [    ["hit","hot","dot","dog","cog"],    ["hit","hot","lot","log","cog"]  ]     

即把字符串A = "hit"轉變成字符串B = "cog",有以下兩種可能: 

"hit" -> "hot" ->  "dot" ->  "dog" -> "cog"; 

"hit" ->  "hot" ->  "lot" ->  "log"  ->"cog"。 


首先把所有的單詞放到一個列表裏面,然後組成一個無相圖,然後從A點開始查找到B點的最短路徑,使用了Dijkstra算法 來查找最短路徑,然後把路徑都打出來。。我用題目的測試用例是通過了,自己寫了幾個測試用例也過了,但是提交以後失敗了。。。汗。。代碼寫得很匆忙。。非常亂哈。。總結一下再發出來,大家做過嗎,都過了麼。。。殘念啊。。。好久沒寫過算法了,,被虐了。。。


#include <string>
#include <vector>
#include <iostream>
#include <set>
#include <map>
#include <algorithm>
using namespace std;


class Solution
{
public:
Solution(){};
    
	
	//比較函數,比較兩個字符串的差別是否爲1,如果不唯一,返回-1
    int cmp(string a,string b)
    {
        int flag=0;
    
        for(int i= 0; i< a.size(); i++ )
            {
                if(a[i]!=b[i])
                    flag++;
                if(flag==2)
                    return -1;
            }
	   if(flag==1)	
       		return 0;
	   else
		    return -1;
    
    }

	
	//輔助函數,返回向量中最後一個元素的索引
    int last(string str,vector<string> strv)
    {
        for(int i=0;i<strv.size();i++)
            if(str == strv.at(i))
                return i;

        return -1;
    }

 
	//計算路徑
    int Size(int a)
        {
            int b=a;
            if(a==0)
                return 9999;
            else
                return b;
        }


		//輔助函數,顯示
 	void display(vector< vector< string > > wayList)
     {
         for(int i=0;i<wayList.size();i++)
             {
                 for(int j=0;j<wayList[i].size();j++)
                    cout << wayList[i].at(j) << "-->";

                cout << endl;
             }
     }
	 
	 //主函數
    vector< vector<string> > findLadders(string start, string end, set<string>& dict)
    {
        vector< vector < string > > Res;    //返回值
        set <string>::iterator si;      
        int max_len=dict.size()+2;          //向量的長度,+2表示起始字符串和結束字符串
        /*
		二維向量保存各個路徑,第一行表示start字符串,第二行表示end字符串,後面各行表示dict的各個字符串
		"hit"-->"hot"...
		"hit"-->"dot"
		...
		...
		*/
		vector< vector< string > > wayList; //路徑的二維向量,
        vector<string> str;                 //保存所有字符串的向量


		if(start == end)
		    return Res;

		/*將數據添加到字符串向量中*/
    	str.push_back(start);
    	str.push_back(end);
     	for (si=dict.begin(); si!=dict.end(); si++) 
         {
         	str.push_back(*si);
         }

		 //構造二維向量列的長度
    	 wayList.resize(max_len);


		 //如果有向量和start只相差一個字符,就將向量添加到二維向量表中
     	for(int i=0;i<max_len;i++)
        {
            if(cmp(str.at(0),str.at(i))==0)
                {
                    wayList[i].push_back(str.at(i));
                }
        }  


		int flag=0;
		while(flag==0)
		{    
			//檢索所有向量
    		for(int i=0;i<max_len;i++)
        	{
			//不檢索1式因爲1保存的是end
            if(i!=1)
            {
				//檢查所有向量
              for(int j=0;j<max_len;j++)
               {
				   //如果該列的向量大於0,表示有一條路徑
                 if(wayList[i].size()>0)
                 {
					//比較該列最後一個元素是否有相鄰的元素                  
                  if(cmp(wayList[i].back(),str.at(j))==0)
                  {
					  //如果有,比較這條路徑的長度和已知的路徑長度的大小
                   if(Size(wayList[j].size())>=Size(wayList[last(wayList[i].back(),str)].size())+1)
                    {
						//如果這條路徑長度小於已知路徑,那將已知路徑刪除,變成這條路徑
						wayList[j].clear();
                        for(int t=0;t<wayList[last(wayList[i].back(),str)].size();t++)
                            wayList[j].push_back(wayList[last(wayList[i].back(),str)].at(t));
                        wayList[j].push_back(str.at(j));
  
  					  	//如果索引爲1,表示已經檢索到end字符串,表示已經找出來一條路徑了
                        if(j==1)
                        {
						  //檢查路徑是否重複	
                         for(int m=0;m<Res.size();m++)
                         {
                           if(Res.at(m)==wayList[j])
                               flag=1;
                                                            
                          }
						  
						  //如果不重複,表示路徑正確,添加到返回值中
                         if(flag==0)
                         {
                             vector <string> res;
                             for(int t=0;t<wayList[j].size();t++)
                                 {
                                     res.push_back(wayList[j].at(t));
                                  }
                             Res.push_back(res);
                          }
                         }//end if(j==1)

                     }//end if(Size(wayList[j].size())>=Size(wayList[last(wayList[i].back(),str)].size())+1)
                    }// end if(cmp(wayList[i].back(),str.at(j))==0)
                   }// end if(wayList[i].size()>0)
                  }//end for   
                }// end if(i!=1)
        	}//end for
			//找到重複路徑,表示已經檢索完畢,結束循環
    		if(flag==1)
        		break;
		}//end while
		for(int i=0;i<Res.size();i++)
		 {
		  Res[i].insert(Res[i].begin(),start);           
		 }
        return Res; 
    }
};


//start 提示:自動閱卷起始唯一標識,請勿刪除或增加。
int main()
{   
    //
	vector < vector <string> > res;
    set <string> strset;
    strset.insert("hot");
    strset.insert("dot");
    strset.insert("dog");
    strset.insert("lot");
    strset.insert("log");
    std::cout << "cog" <<std::endl;
    Solution *s=new Solution();
    res=s->findLadders("hit","cog",strset);
	
	for(int i=0;i<res.size();i++)
	{
		for(int j=0;j<res[i].size();j++)
			cout << res[i].at(j) << "-->";
		cout << " " << endl;
	}
	
	
	
    return 0;
}

輸出:

hit-->hot-->lot-->log-->cog--> 

hit-->hot-->dot-->dog-->cog--> 

結果還是失敗。。呵呵。。。

發佈了54 篇原創文章 · 獲贊 16 · 訪問量 47萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章