[CodeWars][JS]如何判斷給定的數字是否整數

迷路的約翰發表於2015-07-17

問題描述:

We are asking for a function to take a positive integer value, and return a list of all positive integer pairs whose values - when squared- sum to the given integer.

For example, given the parameter 25, the function could return two pairs of 5,0 and 3,4 because 5^2 + 0^2 = 25 and 3^2 + 4^2 = 25.

We might express that in pseudo-code like this:

allSquaredPairs(25) == [[5,0],[3,4]];

 題目本身比較簡單,就是給定一個整數,求出平方和等於該整數的兩個數的序列。

解法

方法1:遍歷所有數字以得到結果

function allSquarePairs(num){
    var temp = Math.sqrt(num);
    var result = [];
    for(var i=0; i<=temp; i++){
        for(var j=i; j<=temp; j++)
            if(i*i+j*j==num)
              result.push([i,j]);
    }
    return result;
}

 然而雖然這個方法是正確的,卻無法通過測試。因為這個演算法的複雜度還是蠻大的,遇到很大的num就得花比較久的時間才能得出結果了。

那麼怎麼降低複雜度呢?我覺得問題主要出在j的遍歷上。對於每個i,j都得從頭遍歷一次,這顯然貢獻了不少的計算量。

我想了想,或許可以用二分查詢,每給定一個i,就在i與temp之間取中值,若j太大,則在前一個區間繼續遍歷;太小,則換成下一個區間。

正當我絞盡腦汁地想怎麼完美地植入二分法的時候,忽然靈光一閃,其實根本沒有必要這麼複雜的:給定了一個i之後,其實我們可以通過計算直接得出j的值,完全沒有必要遍歷的……

方法2: 直接計算j的值

function allSquaredPairs(num) {
  var temp = Math.sqrt(num);
  var result = [];
  var j=0;
  for(var i=0; i<=temp; i++){
    j=Math.sqrt(num-i*i);
    if(isInt(j) && j>=i)
      result.push([i,j]);
  }
  return result;
}

 以上,遍歷i的時候,通過計算(num-i^2)的平方根,判斷是否為整數,如果是,則得到了一組值,否則繼續檢索。如此一來少了一個迴圈計算量就大大減少了,順理成章地通過了測試。

改進

1> isInt()的實現

上面的程式碼中isInt()表示判斷一個數字是否為整數,是則返回true,否則為false。

當然這裡沒必要使用過函式,用簡單的表示式會更方便一些,這裡只是為了佔個位。

那麼問題來了,怎樣判斷一個數字是否為整數呢?

在玩這道題之前,我知道有這些方法:

a>Math.floor(num) == num

對給定的數字取整,如果與原來的數字相等,則為整數。

b>parseInt(num) == num

和上面一樣的,只不過使用不同的方法

c>"^-?//d+$"

當然還可以使用強大的正規表示式。

 

做完這道題之後我才意識到還有更簡潔的形式:

d>num == num | 0

num | 0 捨棄了小數部分,和Math.floor()有些相似。不過還是不一樣的,如果num是負數的時候區別就出來了。

f>num == ~~num

和上面一樣的~

g>num == num>>0

同上~

g>num%1 == 0

與上面的幾個方法相反,這裡檢測的是小數部分。

2> 冗餘的判斷條件

在isInt()的旁邊我們還做了一個j>i的條件,以此避免出現重複序列,比如[0,5]和[5,0]。

實際上這點完全可以在設定temp的值時就過濾掉。只要讓temp=Math.sqrt(num/2)而不是temp=Math.sqrt(num),就可以去掉後面這個j>i的條件了。

 

相關文章