劍指Offer面試題:34.翻轉單詞順序VS左旋轉字符串


一、題目一:翻轉單詞順序

1.1 題目說明

題目一:輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字符的順序不變。為簡單起見,標點符號和普通字母一樣處理。例如輸入字符串"I am a student.",則輸出"student. a am I"。

1.2 解題思路

  第一步翻轉句子中所有的字符。比如翻轉"I am a student."中所有的字符得到".tneduts a ma I",此時不但翻轉了句子中單詞的順序,連單詞內的字符順序也被翻轉了。

  這個步驟我們大多數都很熟悉,看看下面這個Reverse方法,是不是非常熟悉?

    public static void Reverse(char[] array, int start, int end)
    {
        if (array == null || start < 0 || end > array.Length - 1)
        {
            return;
        }

        while (start < end)
        {
            char temp = array[start];
            array[start] = array[end];
            array[end] = temp;

            start++;
            end--;
        }
    }

  第二步再翻轉每個單詞中字符的順序,就得到了"student.a am I"。這正是符合題目要求的輸出。因此,我們可以將上述思路實現為以下代碼:

    public static string ReverseSentense(string sentense)
    {
        if (string.IsNullOrEmpty(sentense))
        {
            return null;
        }

        char[] array = sentense.ToCharArray();
        int start = 0;
        int end = array.Length - 1;

        // Step1.先翻轉整個句子
        Reverse(array, start, end);
        // Step2.再翻轉句中的每個單詞
        start = end = 0;
        while (start < array.Length)
        {
            if (array[start] == ' ')
            {
                start++;
                end++;
            }
            else if (end == array.Length || array[end] == ' ')
            {
                Reverse(array, start, --end);
                start = end + 1;
                end++;
            }
            else
            {
                end++;
            }
        }

        return new string(array);
    }

1.3 單元測試

  (1)測試用例

    // 功能測試,句子中有多個單詞
    [TestMethod]
    public void ReverseTest1()
    {
        string input = "I am a student.";
        string actual = ReverseWordsHelper.ReverseSentense(input);
        string expected = "student. a am I";

        Assert.AreEqual(actual, expected);
    }

    // 功能測試,句子中只有一個單詞
    [TestMethod]
    public void ReverseTest2()
    {
        string input = "Wonderful";
        string actual = ReverseWordsHelper.ReverseSentense(input);
        string expected = "Wonderful";

        Assert.AreEqual(actual, expected);
    }

    // 邊界值測試,測試空字符串
    [TestMethod]
    public void ReverseTest3()
    {
        string input = "";
        string actual = ReverseWordsHelper.ReverseSentense(input);

        Assert.AreEqual(actual, null);
    }

    // 邊界值測試,字符串中只有空格
    [TestMethod]
    public void ReverseTest4()
    {
        string input = "   ";
        string actual = ReverseWordsHelper.ReverseSentense(input);
        string expected = "   ";

        Assert.AreEqual(actual, expected);
    }

    // 魯棒性測試
    [TestMethod]
    public void ReverseTest5()
    {
        string actual = ReverseWordsHelper.ReverseSentense(null);

        Assert.AreEqual(actual, null);
    }

  (2)測試結果

  ①測試用例通過情況

  ②代碼覆蓋率統計

二、題目二:左旋轉字符串

2.1 題目說明

題目二:字符串的左旋轉操作是把字符串前面的若干個字符轉移到字符串的尾部。請定義一個函數實現字符串左旋轉操作的功能。比如輸入字符串"abcdefg"和數字2,該函數將返回左旋轉2位得到的結果"cdefgab"。

2.2 解題思路

  這兩個問題是非常相似的,我們同樣可以通過翻轉字符串的辦法來解決第二個問題。

  以"abcdefg"為例,我們可以把它分為兩部分。由於想把它的前兩個字符移到后面,我們就把前兩個字符分到第一部分,把后面的所有字符都分到第二部分。我們先分別翻轉這兩部分,於是就得到"bagfedc"。接下來我們再翻轉整個字符串,得到的"cdefgab"剛好就是把原始字符串左旋轉2位的結果。

  通過分析可以發現,我們只需要調用三次Reverse方法就可以實現字符串的左旋轉功能

    public static string LeftRotateString(string str, int num)
    {
        if (string.IsNullOrEmpty(str))
        {
            return null;
        }

        int strLength = str.Length;
        char[] array = str.ToCharArray();

        if (strLength > 0 && num > 0 && num < strLength)
        {
            int firstStart = 0;
            int firstEnd = num - 1;
            int secondStart = num;
            int secondEnd = strLength - 1;

            // 翻轉字符串的前面n個字符
            Reverse(array, firstStart, firstEnd);
            // 翻轉字符串的后面部分
            Reverse(array, secondStart, secondEnd);
            // 翻轉整個字符串
            Reverse(array, 0, strLength - 1);
        }

        return new string(array);
    }

2.3 單元測試

  (1)測試用例

    // 功能測試
    [TestCategory("LeftRotate")]
    [TestMethod]
    public void RotateTest1()
    {
        string input = "abcdefg";
        string actual = ReverseWordsHelper.LeftRotateString(input, 2);
        string expected = "cdefgab";

        Assert.AreEqual(actual, expected);
    }

    // 邊界值測試
    [TestCategory("LeftRotate")]
    [TestMethod]
    public void RotateTest2()
    {
        string input = "abcdefg";
        string actual = ReverseWordsHelper.LeftRotateString(input, 1);
        string expected = "bcdefga";

        Assert.AreEqual(actual, expected);
    }

    // 邊界值測試
    [TestCategory("LeftRotate")]
    [TestMethod]
    public void RotateTest3()
    {
        string input = "abcdefg";
        string actual = ReverseWordsHelper.LeftRotateString(input, 6);
        string expected = "gabcdef";

        Assert.AreEqual(actual, expected);
    }

    // 魯棒性測試
    [TestCategory("LeftRotate")]
    [TestMethod]
    public void RotateTest4()
    {
        string actual = ReverseWordsHelper.LeftRotateString(null, 6);

        Assert.AreEqual(actual, null);
    }

    // 魯棒性測試
    [TestCategory("LeftRotate")]
    [TestMethod]
    public void RotateTest5()
    {
        string input = "abcdefg";
        string actual = ReverseWordsHelper.LeftRotateString(input, 0);
        string expected = "abcdefg";

        Assert.AreEqual(actual, expected);
    }

    // 魯棒性測試
    [TestCategory("LeftRotate")]
    [TestMethod]
    public void RotateTest6()
    {
        string input = "abcdefg";
        string actual = ReverseWordsHelper.LeftRotateString(input, 7);
        string expected = "abcdefg";

        Assert.AreEqual(actual, expected);
    }

  (2)測試結果

  ①用例通過情況

  ②代碼覆蓋率

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM