1. 程式人生 > >LintCode刷題指南:字串處理(C++,Python)

LintCode刷題指南:字串處理(C++,Python)

題目:兩個字串是變位詞

題目難度:簡單

題目描述:

寫出一個函式 anagram(s, t) 判斷兩個字串是否可以通過改變字母的順序變成一樣的字串。

解題思路:

C++:引入雜湊的思維,這道題就迎刃而解了。

C++ Code:

class Solution {
public:
    /**
     * @param s: The first string
     * @param b: The second string
     * @return true or false
     */
    bool anagram(string s, string t) {
        // write your code here
        int dic[58];
        for (int i = 0; i < 58; i++)
            dic[i] = 0;
        for ( int i = 0; i < s.size(); i++ )
        {
            if (s[i] == ' ')
                continue;
            int index = s[i] - 'A';
            dic[index]++;
        }
        for ( int i = 0; i < t.size(); i++ )
        {
            if (t[i] == ' ')
                continue;
            int index = t[i] - 'A';
            dic[index]--;
        }
        for ( int i = 0; i < 58; i++ )
        {
            if (i==57 && dic[i]==0)
                return true;
            if (dic[i] == 0)
                continue;
            else
                return false;
        }
    }
};

Python:利用Python的list()方法與sort()方法就可以成功地解決這道問題。

Python Code:

class Solution:
    """
    @param s: The first string
    @param b: The second string
    @return true or false
    """
    def anagram(self, s, t):
        # write your code here
        a = list(s)
        b = list(t)
        a.sort()
        b.sort()
        if a == b:
            return True
        else:
            return False

題目:比較字串

題目難度:簡單

題目描述:

比較兩個字串A和B,確定A中是否包含B中所有的字元。字串A和B中的字元都是大寫字母。

解題思路:

C++:與第一道題幾乎一樣的雜湊思路。

C++ Code:

class Solution {
public:
    /**
     * @param A: A string includes Upper Case letters
     * @param B: A string includes Upper Case letter
     * @return:  if string A contains all of the characters in B return true
     *           else return false
     */
    bool compareStrings(string A, string B) {
        // write your code here
        int dic[26];
        int index;
        for (int i = 0; i < 26; i++)
            dic[i] = 0;
        for (int i = 0; i < A.size(); i++) {
            if (A[i] == ' ')
                continue;
            index = A[i] - 'A';
            dic[index]++;
        }
        for (int i = 0; i < B.size(); i++) {
            if (B[i] == ' ')
                continue;
            index = B[i] - 'A';
            dic[index]--;
        }
        for (int i = 0; i < 26; i++) {
            if (dic[i] < 0)
                return false;
            if (i == 25 && dic[i] >= 0)
                return true;
        }
       
    }
};

Python:利用Python中的list()方法與index()方法,將B中的字元在A中逐個比對,每一次將A中對應的字元刪除,迴圈這個過程。

Python Code:

class Solution:
    """
    @param A : A string includes Upper Case letters
    @param B : A string includes Upper Case letters
    @return :  if string A contains all of the characters in B return True else return False
    """
    def compareStrings(self, A, B):
        # write your code here
        a = list(A)
        b = list(B)
        for n in b:
            if n in a:
                index = a.index(n)
                del a[index]
                continue
            else:
                return False
        return True

題目:字串查詢

題目難度:簡單

題目描述:

對於一個給定的 source 字串和一個 target 字串,你應該在 source 字串中找出 target 字串出現的第一個位置(從0開始)。如果不存在,則返回-1。

解題思路:

C++:通過一個簡單的二層迴圈巢狀進行比對即可解決此題,需要注意的是處理NULL情況。

C++ Code:

class Solution {
public:
    /**
     * Returns a index to the first occurrence of target in source,
     * or -1  if target is not part of source.
     * @param source string to be scanned.
     * @param target string containing the sequence of characters to match.
     */
    int strStr(const char *source, const char *target) {
        // write your code here
        if (source == NULL || target == NULL)
            return -1;
        int index, i;
        int ssize = strlen(source);
        int tsize = strlen(target);
        if (ssize < tsize)
            return -1;
        for (index = 0; index <= ssize - tsize; index++)
        {
            for (i = 0; i <= tsize - 1; i++)
            {
                if (source[i + index] != target[i])
                    break;
            }
            if (i == tsize)
                    return index;
        }
        return -1;
    }
};

Python:和C++的思路是大致相同的,但是可以運用Python中的字串擷取方法,程式碼比C++更簡短,同樣需要注意處理null情況(Python中為None)。

Python Code:

class Solution:
    def strStr(self, source, target):
        # write your code here
        index = 0
        if source is None or target is None:
            return -1
        if len(source) < len(target):
            return -1
        if source == target:
            return 0
        while index <= len(source) - len(target):
            if source[index: index + len(target)] == target:
                return index
            if index == len(source) - len(target) and source != target:
                return -1
            index += 1

題目:亂序字串

題目難度:中等

題目描述:

給出一個字串陣列S,找到其中所有的亂序字串(Anagram)。如果一個字串是亂序字串,那麼他存在一個字母集合相同,但順序不同的字串也在S中。

解題思路:

C++:先將字串陣列中的字串都進行排序,然後運用unordered_map的特性來解決問題,值得一提的是,如果在排序方法中運用O(n^2)的方法,是會判定超時的。

C++ Code:

class Solution {
public:
    /**
     * @param strs: A list of strings
     * @return: A list of strings
     */
    void sort(string &input) {
        int count[26];
        int index;
        for (int i = 0; i < 26; i++) {
            count[i] = 0;
        }
        for (int i = 0; i < input.length(); i++) {
            index = input[i] - 'a';
            count[index]++;
        }
        input = "";
        for (int i = 0; i < 26; i++) {
            for (int j = 0; j < count[i]; j++) {
                input += (char)('a' + i);
            }
        }
    }

    vector<string> anagrams(vector<string> &strs) {
        // write your code here
        vector<string> result;
        vector<string> mystrs = strs;
        for (int i = 0; i < mystrs.size(); i++) {
            sort (mystrs[i]);
        }
        unordered_map<string, int> dic;
        for (int i = 0; i < mystrs.size(); i++) {
            if (dic.find(mystrs[i]) == dic.end())
                dic[mystrs[i]] = 1;
            else
                dic[mystrs[i]]++;
        }
        for (int i = 0; i < mystrs.size(); i++) {
            if (dic[mystrs[i]] == 1)
                continue;
            else
                result.push_back(strs[i]);
        }
        return result;
        }
};

Python:在思路上和C++解法並沒有太大區別,但是由於Python語言本身的一些特性,可以讓程式碼量相較於C++版本的解法大幅減少,運用Python中的字典型別與sorted()方法可以很簡潔地解出這道題。(注:運用sort()方法也可以,但是sort()方法本身會改變list的值,會讓程式碼量略微增多)

Python Code:

class Solution:
    # @param strs: A list of strings
    # @return: A list of strings
    def anagrams(self, strs):
        # write your code here
        dic = {}
        result = []
        for string in strs:
            sortedstr = "".join(sorted(string));
            dic[sortedstr] = [string] if sortedstr not in dic else dic[sortedstr] + [string]
        for key in dic:
            result += dic[key] if len(dic[key]) >= 2 else []
        return result

題目:最長公共子串

題目難度:中等

題目描述:

給出兩個字串,找到最長公共子串,並返回其長度。

解題思路:

C++:這道題固然是可以用遍歷的方法硬解出來的,但是那樣的複雜度是非常不令人滿意的,這裡比較好的方法是運用動態規劃的思想來解答,假設在求最長公共子串對的過程中,A中的子串中最後一個字元的位置為i,B中的子串中最後一個字元的位置為j,實際上就可以把“分別以A[i]與B[j]作為最後一個字元時最長公共字串的長度是多少”當作動態規劃中的子問題,設分別以A[i]與B[j]作為最後一個字元時最長公共字串的長度為longestCommonSubstring[i][j],不難得出longerstCommonSubstring[i][j] = (A[i] == B[j] ? longestCommonSubstring[i - 1][j - 1] + 1 : 0)的推導關係,這樣就可以以動態規劃的思想來解答該題了。

C++ Code:

class Solution {
public:
    /*
     * @param A: A string
     * @param B: A string
     * @return: the length of the longest common substring.
     */
    int longestCommonSubstring(string A, string B) {
        // write your code here
        if (A == "" || B == "")
            return 0;
        int sizeA = A.size();
        int sizeB = B.size();
        int longest = 0;
        vector<vector<int> > list(sizeA, vector<int>(sizeB, 0));
        int initIndex = 0;
        for (int i = 0; i < sizeB; i++) {
            list[initIndex][i] = (A[initIndex] == B[i] ? 1 : 0);
        }
        for (int i = 0; i < sizeA; i++) {
            list[i][initIndex] = (A[i] == B[initIndex] ? 1 : 0);
        }
        for (int i = 1; i < sizeA; i++) {
            for (int j = 1; j < sizeB; j++) {
                list[i][j] = (A[i] == B[j] ? list[i - 1][j - 1] + 1 : 0);
            }
        }
        for (int i = 0; i < sizeA; i++) {
            for (int j = 0; j < sizeB; j++) {
                if (longest < list[i][j])
                    longest = list[i][j];
            }
        }
        return longest;
    }
};

Python:解題思路與C++版本相同,直接貼程式碼。

Python Code:

class Solution:
    """
    @param: A: A string
    @param: B: A string
    @return: the length of the longest common substring.
    """
    def longestCommonSubstring(self, A, B):
        # write your code here
        if (len(A) == 0 or len(B) == 0):
            return 0
        longest = 0
        list = [[0 for i in range(len(B))] for j in range(len(A))]
        for i in range(len(B)):
            if A[0] == B[i]:
                list[0][i] = 1
        for i in range(len(A)):
            if A[i] == B[0]:
                list[i][0] = 1
        for i in range(1, len(A)):
            for j in range(1, len(B)):
                if A[i] == B[j]:
                    list[i][j] = list[i - 1][j - 1] + 1
        for i in range(len(A)):
            for j in range(len(B)):
                if list[i][j] > longest:
                    longest = list[i][j]
        return longest

題目:最長公共字首

題目難度:中等

題目描述:

給k個字串,求出他們的最長公共字首(LCP)。

解題思路:

C++:沒有什麼難點,注意判斷幾個特殊情況即可,例如傳入的字串個數為0,或傳入的字串中存在長度為0的字串。

C++ Code:

class Solution {
public:
    /*
     * @param strs: A list of strings
     * @return: The longest common prefix
     */
    string longestCommonPrefix(vector<string> strs) {
        // write your code here
        string LCP;
        if (strs.size() == 0)
            return LCP;
        for (int i = 0; i < strs[0].length(); i ++) {
            for (int j = 1; j < strs.size(); j++) {
                if (strs[j] == "")
                    return LCP;
                if (strs[j].length() < i + 1)
                    return LCP;
                if (strs[0][i] != strs[j][i])
                    return LCP;
            }
            LCP += strs[0][i];
        }
        return LCP;
    }
};

Python:與C++的解題思路一致,直接上程式碼:

Python Code:

class Solution:
    """
    @param: strs: A list of strings
    @return: The longest common prefix
    """
    def longestCommonPrefix(self, strs):
        # write your code here
        if len(strs) == 0:
            return ""
        if len(strs) == 1:
            return strs[0]
        minlength = min([len(s) for s in strs])
        for i in range(minlength):
            for j in strs:
                if strs[0][i] != j[i]:
                    return strs[0][0: i]
        return strs[0][0: minlength]

題目:轉換字串到整數

題目難度:困難

題目描述:

實現atoi這個函式,將一個字串轉換為整數。如果沒有合法的整數,返回0。如果整數超出了32位整數的範圍,返回INT_MAX(2147483647)如果是正整數,或者INT_MIN(-2147483648)如果是負整數。

解題思路:

C++:此題的難點主要在於需要考慮很多種情況,非常容易遺漏,需要考慮的情況有:傳入的字串長度為零;字串前幾位為‘ ’;正負號情況;字串中間出現的非數字;數字大於INT_MAX或小於INT_MIN。

C++ Code:

class Solution {
public:
    /*
     * @param str: A string
     * @return: An integer
     */
    int atoi(string str) {
        // write your code here
        int index = 0;
        while (str[index] == ' ')
            index++;
        int number = 0, sign = 1;
        if (str[index] == '-' || str[index] == '+') {
            sign = str[index] == '-' ? -1: 1;
            index++;
        }
        for (; index < str.size(); index++) {
            if (str[index] >= '0' && str[index] <= '9') {
                if (number > INT_MAX / 10 || (number == INT_MAX / 10 && str[index] - '0' > 7))
                    return sign == 1 ? INT_MAX: INT_MIN;
                number = number * 10 + (str[index] - '0');
            }
            else
                return number * sign;
        }
        return number * sign;
    }
};

Python:解題思路與C++一致。

Python Code:

class Solution:
    """
    @param: str: A string
    @return: An integer
    """
    def atoi(self, str):
        # write your code here
        index, number, sign = 0, 0, 1
        intmax, intmin = (1 << 31) - 1, -1 << 31
        if str == "":
            return number
        while str[index] == ' ':
            index += 1;
        if str[index] == '-' or str[index] == '+':
            if str[index] == '-':
                sign = -1
            index += 1
        while index < len(str) and str[index] >= '0' and str[index] <= '9':
            if number > intmax / 10 or (number == intmax / 10 and ord(str[index]) - ord('0') > 7):
                return intmax if sign == 1 else intmin
            number = number * 10 + ord(str[index]) - ord('0')
            index += 1
        return number * sign

備註:本人非常樂意分享我的文章,轉載請註明我的部落格地址:http://www.cnblogs.com/matthewli/與原文地址:http://www.cnblogs.com/matthewli/p/7376738.html,謝謝!