1. 程式人生 > 其它 >演算法:字串專項

演算法:字串專項

1. 比較版本號

nowcoder 題目連結
【題目描述】

牛客專案釋出專案版本時會有版本號,比如1.02.11,2.14.4等等。現在給你2個版本號version1和version2,請你比較他們的大小。
版本號是由修訂號組成,修訂號與修訂號之間由一個"."連線。1個修訂號可能有多位數字組成,修訂號可能包含前導0,且是合法的。例如,1.02.11,0.1,0.2都是合法的版本號。
每個版本號至少包含1個修訂號。修訂號從左到右編號,下標從0開始,最左邊的修訂號下標為0,下一個修訂號下標為1,以此類推。

比較規則:

  1. 比較版本號時,請按從左到右的順序依次比較它們的修訂號。比較修訂號時,只需比較忽略任何前導零後的整數值。比如"0.1"和"0.01"的版本號是相等的
  2. 如果版本號沒有指定某個下標處的修訂號,則該修訂號視為0。例如,"1.1"的版本號小於"1.1.1"。因為"1.1"的版本號相當於"1.1.0",第3位修訂號的下標為0,小於1
  3. version1 > version2 返回1,如果 version1 < version2 返回-1,不然返回0.

資料範圍:
1 <= version1.length, version2.length <= 1000
version1 和 version2 的修訂號不會超過int的表達範圍,即不超過 32 位整數 的範圍

示例1
輸入:"1.1","2.1"
返回值:-1
說明:version1 中下標為 0 的修訂號是 "1",version2 中下標為 0 的修訂號是 "2" 。1 < 2,所以 version1 < version2,返回-1

示例2
輸入:"1.1","1.01"
返回值:0
說明:version2忽略前導0,為"1.1",和version相同,返回0

【思路】

  • 既然是比較兩個字串每個點之間的數字是否相同,就直接遍歷字串比較,但是數字前導零不便於我們比較,因為我們不知道後面會出現多少前導零,因此應該將點之間的部分轉化為數字再比較才方便。
  • 可以先將 string 根據'.'劃分為 vector,利用庫函式進行操作,也可以直接遍歷,擷取分隔符'.'之間的字串,轉換為 int,再比較。
#include <string>
#include <vector>
#include <algorithm>

using namespace ::std;
// using std::string;

class Solution
{
public:
    /**
     * 程式碼中的類名、方法名、引數名已經指定,請勿修改,直接返回方法規定的值即可
     *
     * 比較版本號
     * @param version1 string字串
     * @param version2 string字串
     * @return int整型
     */
    int compare(string version1, string version2)
    {
        vector<string> version1Vec = split(version1, ".");
        vector<string> version2Vec = split(version2, ".");
        int len = min(version1Vec.size(), version2Vec.size());
        int i = 0;
        for (; i < len; i++)
        {
            int version1Num = atoi(version1Vec[i].c_str());
            int version2Num = atoi(version2Vec[i].c_str());
            if (version1Num < version2Num)
                return -1;
            else if (version1Num > version2Num)
                return 1;
        }

        // version1 長
        while (i < version1Vec.size())
        {
            if (atoi(version1Vec[i++].c_str()) != 0)
                return 1;
        }

        while (i < version2Vec.size())
        {
            if (atoi(version2Vec[i++].c_str()) != 0)
                return -1;
        }

        return 0;
    }

    /**
     * @param str 待分割的字串
     * @param pattern 以 pattern 來分割字串
     * @return 分割後的 vector<string> 容器
     */
    vector<string> split(const string &str, const string &pattern)
    {
        vector<string> result;
        if (str == "")
            return result;
        string strs = str + pattern;     // 尾部加分割符,統一尾部操作
        size_t pos = strs.find(pattern); // 第一個分隔符位置
        while (pos != strs.npos)         // find 函式若未在字串中找到,返回 npos
        {
            string temp = strs.substr(0, pos); // 分割
            result.push_back(temp);
            strs = strs.substr(pos + 1, strs.size()); // 去掉已分割字元
            pos = strs.find(pattern);
        }
        return result;
    }

    /**
     * 程式碼中的類名、方法名、引數名已經指定,請勿修改,直接返回方法規定的值即可
     *
     * 比較版本號
     * @param version1 string字串
     * @param version2 string字串
     * @return int整型
     */
    int compare2(string version1, string version2)
    {
        int ver1 = 0, ver2 = 0;
        int len1 = version1.size(), len2 = version2.size();
        int i = 0, j = 0;
        while (i < len1 || j < len2)
        {
            while (i < len1 && version1[i] != '.')
            {
                ver1 = ver1 * 10 + (version1[i] - '0');
                i++;
            }

            while (j < len2 && version2[j] != '.')
            {
                ver2 = ver2 * 10 + (version2[j] - '0');
                j++;
            }

            if (ver1 < ver2)
                return -1;
            if (ver1 > ver2)
                return 1;

            i++;
            j++;
            ver1 = 0;
            ver2 = 0;
        }
        return 0;
    }
};