# LeetCode 讀書會第一次 2020/04/21 ## 1. Two sums ### 暴力解 #### JS ```javascript= numss [2,7,11,15], target = 9, Answer: [0, 1] var twoSum = function(nums, target) { for (let i = 0; i < nums.length; i++) { for (let j = i + 1; j < nums.length; j++) { if(nums[i] + nums[j] === target){ return [i,j] } } } }; ``` >Runtime: **168 ms**, faster than 14.97% of JavaScript online submissions for Two Sum. Memory Usage:** 34.8 MB**, less than 41.32% of JavaScript online submissions for Two Sum. ```javascript= var twoSum = function(nums, target) { for(let i = 0; i< nums.length; i++ ){ let index = nums.indexOf(target - nums[i]) if(index !== -1 && i !== index){ return [i, index] } } } ``` > Runtime: **152 ms**, faster than 19.36% of JavaScript online submissions for Two Sum. Memory Usage: **33.9 MB**, less than 97.93% of JavaScript online submissions for Two Sum. #### PHP `array_search` 也是跑 loop, 故也是暴力解。 ```php= function twoSum($nums, $target) { $i=0; while(true){ $x = $target - $nums[$i]; unset($nums[$i]); // 0~n -> 1~n $k = array_search($x,$nums); // O(n) if(gettype($k) == 'integer'){ return [$i, $k]; } $i++; } } ``` > Runtime: **124** ms, faster than 61.24% of PHP online submissions for Two Sum. Memory Usage: **16 MB**, less than 19.35% of PHP online submissions for Two Sum. #### swift ```swift= class Solution { func twoSum(_ nums: [Int], _ target: Int) -> [Int] { for i in 0..<(nums.count-1) { for j in (i+1)..<nums.count { if nums[i] + nums[j] == target { return [i, j] } } } return [] } } ``` >Runtime: 492 ms, faster than 14.87% of Swift online submissions for Two Sum. Memory Usage: 21.2 MB, less than 5.88% of Swift online submissions for Two Sum. #### C++ > Runtime: **8** ms, 95% Memory Usage: **42.2 MB**, 5% - **解題方向** 1. 先 sort 陣列 - 根據 [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort) 裡頭講的,這部分花了 `nlogn` 的時間 2. 把 target 減去陣列元素,並且用 binary search 去找出是否還存在另一個元素 - [geek - binary search](https://www.geeksforgeeks.org/binary-search/) 裡頭有說明這個演算法,時間是 `nlogn` - **說明** 因為有 sort 過,但是回傳時又需要回傳原本值的 index,所以就想說乾脆犧牲記憶體,直接複製一個一樣的陣列,並且使用 `struct data` 這樣的結構去紀錄原本的 index 以及原本的值。 也可以不複製一個 vector,在抓到兩個 operand 出來之後,再回去原本的 vector 做查找,但這樣會使時間變慢,多花 `O(n)` 的時間。 ```c=1 struct data{ int value; int index; }; ``` - **程式碼** - [1.cpp](https://github.com/Jonec76/LTcode/blob/master/1.cpp) ### 解法 2: 快查法 ```javascript= numss [2,7,11,15], target = 9, Answer: [0, 1] var twoSum = function(nums, target) { const comp = {}; for(let i=0; i<nums.length; i++){ let currentNum = nums[i]; if(comp[currentNum]>=0){ return [ comp[nums[i] ] , i] } let relativeNum = target-currentNum comp[relativeNum] = i } } first run -> curNum = 2, comp[2] not exist so set comp[9-2] = 0 second run -> curNum = 7, comp[7] is exist so return [comp[7],i] ``` > Runtime: **52 ms**, faster than 92.48% of JavaScript online submissions for Two Sum. Memory Usage: **34.6 MB**, less than 77.69% of JavaScript online submissions for Two Sum. ```javascript= var twoSum = function(nums, target) { const map = new Map(); let result; nums.forEach( (item, index) => { let indexValue = target - item; if (map.has(indexValue)) { result = [map.get(indexValue), index]; } map.set(item, index); }) return result; }; ``` #### swift ```swift= class Solution { func twoSum(_ nums: [Int], _ target: Int) -> [Int] { var dict = [Int: Int]() for i in 0...nums.count { let difference = target - nums[i] if dict[difference] != nil { return [i, dict[difference]!] } dict[nums[i]] = i } return [] } } ``` >Runtime: **28 ms**, faster than 99.54% of Swift online submissions for Two Sum. Memory Usage: 21.2 MB, less than 5.88% of Swift online submissions for Two Sum. ### 先排序,在查找 複雜度 nlogn nums [2,7,11,15], target = 9, Answer: [0, 1] 先 sort nums -> [2,7,11,15] first run 頭尾 2 + 15 = 17 , 比 target 大,下次大的往右移 second rum 2 + 11 ... ## 7. Reverse Interger Given a 32-bit signed integer, reverse digits of an integer. Example 1: Input: 123 Output: 321 Example 2: Input: -123 Output: -321 Example 3: Input: 120 Output: 21 Input: 2147483648 Output: 0 ### Library 解法 ```javascript= const reverse = x => { const limit = 2147483648; // 0xf7777777 const k = x < 0 ? -1 : 1; const n = Number(String(Math.abs(x)).split('').reverse().join('')); return n > limit ? 0 : n * k; }; ``` ```java= public int reverse(int x) { long res = 0; while (x != 0) { res = res * 10 + x % 10; // 取個位數 x = x / 10; // x: 100 -> 10 } if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) { return 0; } else { return (int)res; } } ``` #### C++ > Runtime: **4** ms, 50% Memory Usage: **6.4 MB**, 100% - **解題方向** 1. 用 `%` 的方法,把每個 digit 都抓出來並且存進 `vector` 2. 要處理 `overflow` 的問題,這裡蠻棘手的 - overflow 簡單來講,就是當值超過某個範圍時就無法正常儲存,以 32bit `int` 來講,其數值範圍是 [ $−2^{31}$ , $2^{31}$ − 1]. 。以大於 $2^{31}$ − 1 來講,當超過此數值時會由正轉負(詳細細節請再另外找資料),所以這邊的處理方法是使用 bitwise 的方式,檢查相加前後的 sign bit 是否相同。 但是少思考一點,當超過的值只超過一些,此時會是負數,但超過太多時又會是正數,以 `1534236462` 為例,其反過來會是 `-1648642945`,但以 `1534236469` 為例,其相反卻是 `1056389759`。==此部分的處理應該有更好的方法==,但這邊使用最粗糙的檢查法去檢查。 - **程式碼** - [7.cpp](https://github.com/Jonec76/LTcode/blob/master/7.cpp)