1. 程式人生 > >《演算法設計與分析》第二週作業

《演算法設計與分析》第二週作業

《演算法設計與分析》第二週作業

標籤(空格分隔): 課堂作業


姓名:李**
學號:16340114
題目:ZigZag Conversion(https://leetcode.com/problems/zigzag-conversion/description/


題目概要

  輸入一個字串,將該字串按類z形狀排列,再按橫向順序輸出新的字串,詳情點選題目連結。

思路

嘗試一

  建立一個矩陣,把輸入字串按照題目規則填入矩陣中,矩陣剩餘位置留空,再按行遍歷矩陣,得到目的輸出。這樣做貌似很暴力,而且當行數增多的時候,矩陣裡的空位會變得很多,且遍歷的開銷也會變得非常大。這種解法似乎不現實。
這裡寫圖片描述

嘗試二

  採用分而治之的思想,將按z型排列的字串分成若干個相同的組(如圖所示),在一個組內建立輸入字串與輸出字串的對映函式,繼而推廣到所有組別,得出通用的轉換公式。

  注意到,在分組的時候,最後一組可能與其他組不同,這使得對映函式的建立變得困難,因此,先假定最後一組與其他組的模式都是相同的,之後再處理最後一組(參差不齊)的問題。

在建立轉換公式之前,先計算一些重要的引數:
  每組的字元個數(靠觀察可得):entitiesInSet = 2 * numRows - 2;
  總組數(同樣靠觀察可得):numSet = ⌈ inputString.length() / entitiesInSet ⌉(向上取整);
這裡寫圖片描述

在每一組中,分為四種情況:

1.組內第一個字元

  稍微觀察一下(感覺這題就是在找規律),每組的第一個字元對應輸出字元下標為 分組序號setIndex,即

outputString[setIndex] = inputString[oldStringIndex];

這裡寫圖片描述

2.組內第一列中間字元(除去第一個和最後一個字元)

  第二行的元素對應的下標為 【第一行的字元數 + 組號 * 2】
  第三行的元素對應的下標為 【第一行的字元數 + 第二行的字元數 + 組號 * 2】
  ···
  第i行的元素對應的下標為 【第一行的字元數 + 第二行的字元數 + ··· + 第i - 1行的字元數 + 組號 * 2】

  第一行的字元數為總組數numSet,剩餘行的字元數為總組數乘二numSet * 2。

  可以得到對第一列中第i個(對應第i+1行)字元。(圖中第一組的A是第1個(i = 1),Y是第二個 (i = 2))對應的下標為 【組數 * (2 * i - 1) + 組號 * 2】, 即

outputString[numSet * (2 * i - 1) + setIndex * 2] = inputString[oldStringIndex];

這裡寫圖片描述

3.組內第一列最後一個字元

  用類似情況2的推算,對應的下標為 【除最後一行的總字元數(第一行的字元數 + 第2行 ~ 第numRows - 1行)的字元數 + 組號】,即

outputString[numSet * (2 * numRows - 3) + setIndex] = inputString[oldStringIndex];

這裡寫圖片描述

4.組內在斜線上的元素

  與第2中情況類似,只是對應的下標多了1,組數 * (2 * i - 1) + 組號 * 2 + 1,即

outputString[numSet * (2 * i - 1) + setIndex * 2 + 1] = inputString[oldStringIndex];

這裡寫圖片描述

  這四種情況都處理完之後,就開始處理最後一組(參差不齊)的問題。
  其實這個問題還蠻好處理的,將最後一組單獨拿出來處理,先假定最後一組是完整的,與其他組一樣處理,在遇到輸入字元不存在的位置時,將一個特殊符號(如“*”,輸入字串裡沒有該符號)放入輸出字串中。將全部完成後再次遍歷輸出字元,遇到該特殊字元(*)時將該字元剔除,即可得到最終答案。

具體實現

  先計算“思路”中的兩個重要引數。
  再以組號為引數進行迴圈,處理除最後一組之外的組。同時使用一個下標變數,按順序對輸入字元進行處理,每處理完一個字元該變數自增。
  在每組中按照思路中的4種情況按順序處理,將得出的公式轉化為程式碼即可,特別地,在第3種情況中,隨著輸入字元下標的遞增,行數是遞減的,這時只要將迴圈變數遞減即可。
  之後處理最後一組,使用巨集定義檢測下標是否越界,如越界,則將‘*’輸出到輸出字串。
  最後建立一個新的字串,將中間輸出字串的非’*’字元吸收即可。

心得

  雖然這次沒用到課堂上講的大師定理,但是分治思想的應用還是使得這個問題簡單了許多(比用矩陣蠻幹好多了不是嗎),將一個大問題分解成一個個的小問題,這樣思考起來不會那麼吃力,而且把小問題解決了大問題也就自然而然地就解決了。

原始碼:

#define entityOrBubble (oldStringIndex >= s.length() ? '*' : s[oldStringIndex]);

class Solution 
{
public:
    string convert(string s, int numRows) 
    {
        if (s.length() == 0 || numRows == 1)
            return s;

        int entitiesInSet = 2 * numRows - 2;
        int numSet = ceil( (float)s.length() / entitiesInSet );

        string tempString(numSet * entitiesInSet, '*');
        // common set
        for (int setIndex = 0; setIndex <= numSet - 2; ++setIndex)
        {
            int oldStringIndex = setIndex * entitiesInSet;

            //first entity in each set
            tempString[setIndex] = s[oldStringIndex];
            oldStringIndex++;

            //the remain entities of the first column in each set  except the last one
            for (int i = 1; i <= numRows - 2; ++i)
            {
                tempString[numSet * (2 * i - 1) + setIndex * 2] = s[oldStringIndex];
                oldStringIndex++;
            }

            //the last entity of the first column in each set 
            tempString[numSet * (2 * numRows - 3) + setIndex] = s[oldStringIndex];
            oldStringIndex++;

            //the remain entities of each set
            for (int i = numRows - 2; i >= 1; --i)
            {
                tempString[numSet * (2 * i - 1) + setIndex * 2 + 1] = s[oldStringIndex];
                oldStringIndex++;
            }
        }

        // the last set
        {
            int setIndex = numSet - 1;

            int oldStringIndex = setIndex * entitiesInSet;

            //first entity in each set
            tempString[setIndex] = s[oldStringIndex];
            oldStringIndex++;

            //the remain entities of the first column in each set  except the last one
            for (int i = 1; i <= numRows - 2; ++i)
            {
                tempString[numSet * (2 * i - 1) + setIndex * 2] = entityOrBubble;
                oldStringIndex++;
            }

            //the last entity of the first column in each set 
            tempString[numSet * (2 * numRows - 3) + setIndex] = entityOrBubble;
            oldStringIndex++;

            //the remain entities of each set
            for (int i = numRows - 2; i >= 1; --i)
            {
                tempString[numSet * (2 * i - 1) + setIndex * 2 + 1] = entityOrBubble;
                oldStringIndex++;
            }
        }

        string finalString(tempString.length() + 1, '\0');
        int finalStringIndex = 0;
        for (int i = 0; i < tempString.length(); ++i)
        {
            if(tempString[i] != '*')
            {
                finalString[finalStringIndex] = tempString[i];
                finalStringIndex++;
            }   
        }

        return finalString;
    }
};