1. 程式人生 > >經典演算法面試題目-判斷s2是否是s1的旋轉字串(1.8)

經典演算法面試題目-判斷s2是否是s1的旋轉字串(1.8)

題目

Assume you have a method isSubstring which checks if one word is a substring of another. Given two strings, s1 and s2, write code to check if s2 is a rotation of s1 using only one call to isSubstring ( i.e., “waterbottle” is a rotation of “erbottlewat”).

假設你有一個isSubstring函式,可以檢測一個字串是否是另一個字串的子串。 給出字串s1和s2,只使用一次isSubstring就能判斷s2是否是s1的旋轉字串, 請寫出程式碼。
例如:”waterbottle”是”erbottlewat”的旋轉字串。

解答

題目說我們使用一次isSubstring函式就可以判斷s2是否是s1的旋轉字串, 如果從原始字串s1和s2直接入手肯定不行,因為它們根本不存在子串關係。 如果不斷地旋轉字元,然後呼叫isSubstring,又需要呼叫多次的isSubstring。 而且通過旋轉字元再判斷,可以直接用等號判斷,根本用不上isSubstring。

既然如此,我們就要考慮去改變原始字串。要判斷a串是否是b串的子串, 一般情況下都會有b串長度大於a串,長度相等的話就直接判斷它們是不是相等的串了。 我們可以考慮把串s1變長,然後呼叫一次isSubstring判斷s2是否是s1變長後的子串, 如果是,就得出s2是s1的旋轉字串。s1怎麼變長呢?無非就是s1+s1或是s1+s2, s2一定是s1+s2的子串,因此這樣做沒有任何意義。而s1+s1呢? 我們就上面的例子進行討論:s1=waterbottle,s2=erbottlewat. 則:

s1 + s1 = waterbottlewaterbottle

很容易可以發現,s1+s1其實是把s1中每個字元都旋轉了一遍,而同時保持原字元不動。 比如waterbottle向右旋轉2個字條應該是:terbottlewa,但如果同時保持原字元不動, 我們得到的就是waterbottlewa,而terbottlewa一定是waterbottlewa的子串, 因為waterbottlewa只是在terbottlewa的基礎上再加上一條原字元不動的限制。 因此s1+s1將包含s1的所有旋轉字串,如果s2是s1+s1的子串,自然也就是s1 的旋轉字串了。

首先,我們來了解一個函式:
a.find(b) 表示查詢字串a是否包含子串b,若查詢成功,返回按查詢規則找到的第一個字元或子串的位置;若查詢失敗,返回npos,即-1(打印出來為4294967295)。

接下來,利用這個函式,我們可以很方便的寫出判斷s2是否是s1的旋轉字串的程式碼。

關鍵程式碼:

//判斷s2是不是s1的子串
bool isSubstring(string s1, string s2){
    if(s1.find(s2) != string::npos) return true;
    else return false;
}

//防範一下,以及呼叫:isSubstring(s1+s1, s2)
bool isRotation(string s1, string s2){
    if(s1.length() != s2.length() || s1.length()<=0)
        return false;
    return isSubstring(s1+s1, s2);
}

完整程式碼:

#include <iostream>
#include <string>
using namespace std;

bool isSubstring(string s1, string s2){
    //a.find(b)查詢字串a是否包含子串b。string::npos(很大的無符號整數)也可以認為就是-1。
    if(s1.find(s2) != string::npos) return true;
    else return false;
}
bool isRotation(string s1, string s2){
    //防範一下!如果s2的長度和s1的不相等,肯定就不可能s2是s1的旋轉子串了。
    if(s1.length() != s2.length() || s1.length()<=0)
        return false;
    return isSubstring(s1+s1, s2);
}

int main(){
    string s1 = "apple";
    string s2 = "pleap";
    if(isRotation(s1, s2)){
        cout<<s2+"是"+s1+"的旋轉字串"<<<<endl;
    }
    //cout<<string::npos<<endl; //4294967295
    //cout<<s1.find(s2)<<endl;  //4294967295
    return 0;
}