因爲需求只是求出循環週期,所以不關心其小數形式。利用小學三年級計算除法的步驟。當除得的餘數重複出現時,兩次步驟之間的間隔數目即爲小數但循環週期。算法
ps: 函數傳入參數爲兩個u64.數組
fn cycle(m:u64,n:u64) -> Option<u64>{ use std::collections::HashMap; let mut residues = HashMap::new(); let mut residue = m%n; let mut count:u64 = 0; residues.insert(residue, count); loop{ count +=1; residue = (residue*10)%n; if residue == 0{ return None; } if let Some(res) = residues.get(&residue){ return Some(count-res); } residues.insert(residue, count); } } #[test] fn test() { //1.42857 142857 142857 ... assert!(Some(6) == cycle(10,7)); }
用HashMap
的好處是,hash查找的時間複雜度爲O(1),每次查詢所消耗的的時間固定。但缺點是每次查詢都須要計算一次hash值,遇到hash碰撞還會使得性能降低。總的來講比較適合循環週期較長的狀況。函數
代碼中,hash表記錄的值是這個餘數出現的序數。能夠用vec
代替,則餘數出現但序數就是該數在數組中的索引。「呆?!看代碼。。。」oop
fn cycle(m:u64,n:u64) -> Option<u64>{ let mut residues = vec![]; let mut residue = m%n; residues.push(residue); loop{ residue = (residue*10)%n; if residue == 0{ return None; } if let Some(res) = residues.iter().position(|&item|item==residue){ return Some((residues.len() -res) as u64); } residues.push(residue); } }