搜尋此網誌

2021年12月30日 星期四

系列中最大的乘積(2)

 緣起:


    接續這篇文章的教學,完整程式碼在這裡

1000 位數字用字串記錄


字串轉數字:



    自訂一個 str_to_num 的函式,傳入字元,並用 int() 把字元轉成數字 0~9 (23),如果轉完後的數字是 0 的話,我們把它當成 1 (24),最後回傳轉換完成的數字 (27)

尋找所有 0 出現的位置:

    

    big_number_len 用來記錄那數字的長度 (其實好像直接寫 1000 也可以...),zero_positions 是個陣列,用來記錄 1000 位數中所有 0 出現的位置,start_position 在 while 迴圈裡會用到,初始值為 0,表示從最前面找起。

    我們可以用字串的 find(目標值, 起始位置, 終止位置) 來找到 '0' 出現的地方,這個函式只會回傳第一個找到的位置,我們用 position 來記錄(34),並把找到的位置加到 zero_positions 的後方 (37),接著更新 start_position 的位置 (38) (假如你在 4 的位置找到了 0,那麼你之後要繼續找的話,應該從位置 5 開始找起),一直到找不到 '0' 為止,這時 find 的函式就會回傳 -1,我們也就能以此來判斷是否要結束找 0 的工作 (35)。

    做完後,zero_postions 裡的值就會是所有出現 0 的位置,由小到大排序。

初始設定:



    N 記錄使用者輸入的數字 (相鄰 N 個數字) (40),left_index 記錄某一系列的開始 (42),right_index 記錄某一系列的結束 (43),zero_index 是給 zero_positions 用的 index (44),就是 zero_positions 陣列的索引,初始值為 0,,而 zero_length 是記錄 zero_positions 陣列的長度 (45)

    current_product 是記錄系列的乘積,初始值設為 1,方便之後的連乘運算 (46),max_product 用來記錄我們能找到的最大系列的乘積,初始值設為 0 (47)

    再來我們要先直接算出前 N 位的乘積 (48),先得到最初的結果後 (49) 才能接下去做我們前一篇文章提到的 "除左乘右" 動作。

    最後,先確認一下最初系列的區間內有沒有 0 (51),如果沒有的話,我們就能先把 max_product 指派為最前 N 位數的乘積。

開始處理:



    我們用一個 while 迴圈來做,終止的條件是 right_index 到達 1000 位數的倒數第二個位數時 (因為迴圈裡會有 right_index+1 的動作)。再來是除以系列第一個數 (55),之後把 left_index 往前挪 1 (56),right_index 則是要先挪 1 位後才跟我們的 current_product 做相乘 (57, 58)

    接著是檢查目前所標記 0 的位置 (zero_position[zero_index]),有沒有落後於系列 (跟 left_index 做比較),然後加一個 and 的條件,確保 zero_index+1 後不會超出 zero_positions 陣列的長度 (60)。zero_index 加 1 後,我們就會移到下一個標記 0 的位置 (那位置會更大,因為 zero_positions 的值是由小到大排序) (61)

    如果現在 0 的位置沒有在系列中 (跟記著系列最右位置的 right_index 比較) (63),代表目前的系列中不包含 0,所以乘出來的結果不會是 0,然後我們就能接著檢查 current_product 的值是否有大於目前記錄的乘積最大值 (max_product) (64),有的話就把 max_product 的值用 current_product 取代掉 (65),最後,整個 while 做完後,那個 max_prodcut 就是我們要的系列中的最大乘積。

結束 ~


沒有留言:

張貼留言