Posts

Showing posts from May, 2021

[LeetCode] #561. Array Partition I

題目 Given an integer array nums of 2n integers, group these integers into n pairs (a1, b1), (a2, b2), ..., (an, bn) such that the sum of min(ai, bi) for all i is maximized. Return the maximized sum. 直覺解 構想: 由小到大排序之後,兩兩一組取最小的數字相加,也就是,取 index 為偶數的數字相加。 python3 實作: class Solution:     def arrayPairSum(self, nums: List[int]) -> int:         nums.sort()         return sum(nums[::2]) 效能: Runtime: 264 ms, faster than 62.64% of python3 online submissions for Array Partition I. Memory Usage: 16.7 MB, less than 82.74% of python3 online submissions for Array Partition I.

[LeetCode] 49. Group Anagrams

題目 Given an array of strings strs, group the anagrams together. You can return the answer in any order. An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once. 1 < = strs.length <= 10 4 0 <= strs[i].length <= 100 strs[i] consists of lower-case English letters. 直覺解 構想: result 的格式預計就是要回傳的答案。比對 strs 中每個字串,是否和 result 中任一元素的第一個元素,都使用一樣且數量相同的字母。比對的方式是,雙方同時刪掉某個特定字母,刪完之後雙方長度是否一樣。 javascript 實作: const groupAnagrams = function(strs) {     if (strs.length < 2) { return [strs]}     const result = []     strs.forEach(str => {         let isGrouped = false         for (const group of result) {             let isAnagram = true             if (group[0].length !== str.length) {                 isAnagram = false                 continue             }             let originalLetters = group[0]             let string = str            

[LeetCode] #18. 4Sum

題目 Given an array nums of n integers, return an array of all the unique quadruplets [nums[a], nums[b], nums[c], nums[d]] such that: 0 <= a, b, c, d < n a, b, c, and d are distinct. nums[a] + nums[b] + nums[c] + nums[d] == target You may return the answer in any order. 直覺解 構想: 找出所有可能的組合,刪掉重複的組合,然後回傳答案。 javascript 實作: const fourSum = function(nums, target) {     let a = 0     let b = 1     let c = 2     let d = 3     const result = []     while (a < nums.length - 3) {         while (b < nums.length -2) {             while (c < nums.length -1) {                 while (d < nums.length) {                     if (nums[a] + nums[b] + nums[c] + nums[d] === target) {                         let isDuplicated = false                         const array = [nums[a], nums[b], nums[c], nums[d]].sort((a, b) => a - b)                         for (const item of result) {                             if (                                 array

資料關聯

以飲料店的商品種類為例,假設我們現在有飲料和杯子兩種資料。 飲料: id name 1 綠茶 2 紅茶 3 青草茶 杯子: id size 1 500 2 600 3 700 一對一(One to One) 若飲料和杯子是一對一的關係,那麼情況就類似這樣: 綠茶只用 500 cc 的杯子裝 紅茶只用 600 cc 的杯子裝 青草茶只用 700 cc 的杯子裝 一種飲料只有一個尺寸的杯子,而且一個尺寸的杯子也只對應到一種飲料。在這種情況下要建立關聯,有下列兩種方式,擇一即可。這兩種做法在技術上效果是一樣的,不過語意解讀上可能不太一樣。 把關聯欄位加在飲料(語意上,是飲料有杯子這個屬性) 把關聯欄位加在杯子(語意上,是杯子有飲料這個屬性) 把關聯欄位加在飲料的資料表: id name cup_id 1 綠茶 1 2 紅茶 2 3 青草茶 3 把關聯欄位加在杯子的資料表: id size drink_id 1 500 1 2 600 2 3 700 3 一對多(One to Many) 若飲料和杯子是一對多的關係,那麼情況就類似這樣: 綠茶用 500 cc、700 cc 的杯子裝 紅茶只用 600 cc 的杯子裝 一種飲料有許多尺寸的杯子,而且一個尺寸的杯子只對應到一種飲料。 或者是這樣: 綠茶、紅茶、青草茶都只用 500 cc 的杯子裝 一個尺寸的杯子對應到許多種飲料,而且一種飲料只有一個尺寸的杯子。 在這種情況下要建立關聯,一般會選擇加在多的那一邊。如果加在少的那一

封包傳輸

什麼是封包(network packet) 在 packet-switched network 中被傳輸的東西就叫做封包。封包分為 control information 和 user data 兩個部分,control information 紀錄著要將封包送去哪裡的相關資訊,user data 則是要給對方的資料。以包裹來比喻的話,control information 紀錄著收件者、寄件者等等資訊,user data 則是包裹的內容物。 一筆大的資料,可先分割為若干封包後再進行傳輸。 封包傳輸(Packet switching) 封包傳輸可分為兩種 communication mode:connectionless 和 connection-oriented。 connectionless mode 此種模式,不需要預先建立與接收方之間的通道,因此,在同一個通道中,可以同時進行多個通訊。但代價是,要在 control information 攜帶更多訊息,例如目的地位址、來源位置、埠號等等,可能還會有封包的序號。因為每個封包可能是經由不同的路徑抵達目的地,所以送出封包的順序,和最後接收方收到的順序可能是不一樣的,所以,若封包的順序很重要的話,需要有封包序號才能將封包以正確的順序排列。 屬於此模式的協定有:Internet Protocol(IP)、User Datagram Protocol(UDP)。 connection-oriented mode 此種模式,在傳輸資料前,要預先建立與接收方之間的通道,因此 control information 需要攜帶的資料比較少,例如,不需要位址資訊,只需要 connection identifier。但代價是,一旦建立通道,其他的傳輸就不能使用此通道。 屬於此模式的協定有:Transmission Control Protocol(TCP)。 參考資料 Network packet - 英文維基百科 Packet switching - 英文維基百科 封包傳訊vs.電路傳訊 電腦網路與連結技術:第四章 網路層

[LeetCode] 260. Single Number III

題目 Given an integer array nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once. You can return the answer in any order. You must write an algorithm that runs in linear runtime complexity and uses only constant extra space. 直覺解 構想: 紀錄每個數字出現幾次,最後回傳只出現一次的數字。 javascript 實作: const singleNumber = function(nums) {     if (nums.length === 2) { return nums }     const result = []     const seenNumber = {}     let i = 0     while (i < nums.length) {         seenNumber[nums[i]] ? seenNumber[nums[i]]++ : seenNumber[nums[i]] = 1         i++     }     for (const num in seenNumber) {         if (seenNumber[num] === 1) {             result.push(num)         }     }     return result } 效能: Runtime: 88 ms, faster than 54.68% of JavaScript online submissions for Single Number III. Memory Usage: 42.7 MB, less than 9.36% of JavaScript online submissions for Single Number III. 犯過

TCP/ IP 通訊協定

為什麼要有通訊協定 不同機器之間,若要能夠溝通的話,需要大家都使用相同的語言。所有人都遵守通訊協定,就不會出現語言隔閡。 什麼是 TCP/ IP 通訊協定 要實現「不同機器之間能夠溝通」,從硬體到軟體,有許多工作要完成。為了讓這份工作比較容易進行,所以將工作拆分成好幾個部分,各自獨立完成;以後若要維護的話,哪個部分有問題,只要維修那個部分就好,不必把所有部分都拿出來檢查,降低維修難度。 至於工作到底要怎麼拆分,不同的模型有不同的建議。OSI(Open System Interconnection)模型切成七層工作,DoD(Department of Defense Model)模型則是切成四層,每一層都有不同的通訊協定。雖然目前實作上通常不是採用 OSI 模型,但為了方便理解「不同機器之間能夠溝通」的機制,通常會用 OSI 模型講解,也會試著將 DoD 模型對應到 OSI 模型。 DoD 模型中有許多通訊協定,不過以 TCP、IP 這兩個通訊協定最具有代表性,所以 DoD 模型又稱為 TCP/ IP 模型。TCP 協定對應到 OSI 模型中的傳送層,IP 協定則是對應到網路層。 TCP、IP 通訊協定負責什麼工作 TCP 協定 發送端的 TCP,和接收端的 TCP,會先進行三向交握,確認彼此能夠順利傳輸資料,才正式開始傳輸資料。 我們可以把要傳輸的資料想像成要郵寄的包裹,郵寄時,包裹會有尺寸或重量的限制,同樣地,傳輸的資料也會有大小的限制。如果資料太大了,TCP 會拆分成小包裹,並且幫每個小包裹編號(以便接收端最後能把小包裹還原成大包裹),並注意是否每一個小包裹都成功送達,若沒有成功送達,TCP 會再補上缺少的小包裹。如果資料太小了,TCP 會幫包裹灌水,以符合大小的下限。 IP 協定 IP 位址就像收件地址,以便確認要將包裹送去哪個主機。IP 位址目前有兩種版本,IPv4 用 32 位元儲存地址,IPv6 用 128 位元儲存地址。所以 IPv6 有比較多的地址可以分配給不同的主機。 IPv4 以 IPv4 而言,位址可以切成兩個部分,第一部分代表 Net ID,第二部分代表 Host ID。相同的 Net ID,代表主機位在相同的 IP 網段,相同 IP 網段的主機之間可以用廣播的方式傳遞資料,而不必透過路由。可以從 N

[LeetCode] 137. Single Number II

題目 Given an integer array nums where every element appears three times except for one, which appears exactly once. Find the single element and return it. You must implement a solution with a linear runtime complexity and use only constant extra space. 1 <= nums.length <= 3 * 10 4 -2 31 <= nums[i] <= 2 31 - 1 Each element in nums appears exactly three times except for one element which appears once. 直覺解(失敗) 構想: 模仿 Single Number 那一題,製造一個「出現三次就會歸零」的函式。 javascript 實作: const singleNumber = function(nums) {     function becomeZeroWhenAppearsThreeTimes (a, b, c) {         return (a | b | c) & (~a | ~b | ~c)     }     let result = nums[0]     for (let i = 1; i < nums.length; i += 2) {         result = becomeZeroWhenAppearsThreeTimes(result, nums[i], nums[i + 1] || 0)     }     return result } 錯誤: console.log(singleNumber([0,1,0,1,0,1,99])) // 98 Debug function dec2bin(dec) {     return (dec >>> 0).toString(2) }

CORS 是什麼?

什麼時候會用到 CORS CORS:跨來源資源共用(Cross-Origin Resource Sharing) 舉例:瀏覽器連線到 http://localhost:3000 的伺服器,伺服器回傳的 HTML 檔案中,在 javascript 裡用 XMLHttpRequest 請求 https://example.com 的資源。 只要通訊協定、網域、和通訊埠三者中有一個不同,就屬於跨來源資源請求。 所以 http://localhost:3000 請求 https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css 上的資源,就屬於跨來源資源請求。 為了保護資訊安全,跨來源資源請求是受到限制的。若想完成跨來源資源請求,需要遵守 CORS 的規範,不然就會失敗。 CORS 的規範是什麼 簡單請求、非簡單請求 跨來源資源請求,分為簡單請求,和非簡單請求。 定義:符合底下所有條件的就是簡單請求,不符合的就是非簡單請求 HTTP 方法是 GET、HEAD 或 POST 自訂的請求頭只能是 Accept、Accept-Language、Content-Language 或 Content-Type(此項的值只能是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain) If the request is made using an XMLHttpRequest object, no event listeners are registered on the object returned by the XMLHttpRequest.upload property used in the request; that is, given an XMLHttpRequest instance xhr, no code has called xhr.upload.addEventListener() to add an event listener to monitor the upload.(字面上的意思似乎是,如果是用 XMLHttpRequest 物件發出請求,而且請

[LeetCode] 80. Remove Duplicates from Sorted Array II

題目 Given a sorted array nums, remove the duplicates in-place such that duplicates appeared at most twice and return the new length. Do not allocate extra space for another array; you must do this by modifying the input array in-place with O(1) extra memory. 直覺解 構想: 宣告兩個指針 filteredNumIndex 和 i,filteredNumIndex指在「出現不超過兩次」的數字上,i 迭代整個 nums 陣列。若迭代到符合「出現不超過兩次」的數字,filteredNumIndex 會把這個數字留下來,反之就不留。 javascript 實作: const removeDuplicates = function(nums) {     if (nums.length === 1) { return 1 }     let filteredNumIndex = 0     let duplicateCount = 1     let i = 1     while (i < nums.length) {         if (nums[filteredNumIndex] === nums[i]) {             if (duplicateCount < 2) {                 filteredNumIndex++                 nums[filteredNumIndex] = nums[i]                 duplicateCount++             }         } else {             filteredNumIndex++             nums[filteredNumIndex] = nums[i]             duplicateCount = 1         }         i++     }

Alpha Camp 全端開發課程學習心得

我喜歡邏輯,在哲學系求學時期,我花最多時間的科目,是形式邏輯。但是我一直不明白這個我相對擅長的科目,到底能用在什麼地方。我的邏輯能力,並沒有好到足夠讓我走上學術研究的路,那麼,或許我可以試著寫程式? 學生時期的我,自認沒有錢,但是有時間。捨不得花錢去上程式設計課程,寧願自己找資源學習。去上過一些免費的程式入門課程,c++ 和 python,對我而言不是很難,但是學完之後,我還是看不出來,要怎麼靠學到的東西解決生活中遇到的問題,漸漸地就沒有動力繼續學下去。 直到出社會,存了點錢,也漸漸體會到時間的重要,終於捨得花錢投資自己,到 Alpha Camp 上專業的課程,而不是無頭蒼蠅自己亂找一通,省下許多時間,也看到自己學的東西是真的能用的,讓我有動力繼續學下去。 我還記得學到串接 api 的時候,心裡真是太激動了。以前在學免費課程時,就隱約有種「我寫的程式,範圍只侷限在我的電腦上」的貧瘠感覺,而在知道了 api 後,發現「我寫的程式可以跟世界接上線了」,頓時覺得自己非常富有。不過,後來才知道,串別人的 api 服務通常是要付費的。 大概是受了形式邏輯的影響,我在學習程式語言時,總是試圖去辨認,哪些東西是比較基本的,基本的東西是透過什麼樣的規則組合出複雜的東西。例如,變數、array、for 迴圈和 function 是基本的東西,可以用這些基本的東西組合出 array 的 reduce 方法,像這樣: function mimicReduce(array, reducerFunction, initialValue) {     if (initialValue) {         let accumulator = initialValue         for (let i = 0; i < array.length; i++) {             accumulator = reducerFunction(accumulator, array[i])         }         return accumulator     } else {         let accumulator = array[0]         for (let i = 1; i < array.length; i

[LeetCode] 136. Single Number

題目 Given a non-empty array of integers nums, every element appears twice except for one. Find that single one. You must implement a solution with a linear runtime complexity and use only constant extra space. Constraints:  1 <= nums.length <= 3 * 10 4 -3 * 10 4 <= nums[i] <= 3 * 10 4 Each element in the array appears twice except for one element which appears only once. 直覺解 構想: 迭代整個陣列,紀錄每個數字出現幾次。最後從記錄裡找出只出現一次的數字。 javascript 實作: const singleNumber = function(nums) {     const countNumber = {}     let i = 0     while(i < nums.length) {         if (!countNumber[nums[i]]) {             countNumber[nums[i]] = 1         } else {             countNumber[nums[i]] ++         }         i++     }     i = 0     while(i < nums.length) {         if (countNumber[nums[i]] === 1) {             return nums[i]         }         i++     } } 效能: Runtime: 100 ms, faster than 37.71% of JavaScript online submissions for Single Number. Me

多人協作 simple twitter 專案心得

多人協作 simple twitter 專案,是 Alpha Camp 學期三 的最後一份作業。我們這組的分工是前端兩個人,後端兩個人,我負責後端。 專案成果 Demo 使用者登入頁面: https://tingchun0113.github.io/twitter-vue-2020/#/login/ 測試帳號:user1@example.com 密碼:12345678 管理員登入頁面: https://tingchun0113.github.io/twitter-vue-2020/#/admin/ 測試帳號:root@example.com 密碼:12345678 後端 Heroku 伺服器: https://twitter-socket-1.herokuapp.com 程式碼 後端 GitHub: https://github.com/s091173/twitter-api-2020 前端 GitHub: https://github.com/mryixue/twitter-vue-2020 我負責的任務 建立 model,和建立 model 之間的關聯 加入 JWT 驗證機制 路由: /api/admin /api/followship /api/chat /api/user 底下的七條路由: /current、/top、/:id、/:id/followings、/:id/tweets、/:id/replied_tweets、/:id/likes 將專案部署到 heroku 撰寫 api 文件和 README 在我所知的範圍內,盡量實現「不要相信前端來的資料,後端一定要再驗一次」的精神 實作伺服器端的公開即時聊天功能、在資料庫保存公開聊天的歷史訊息 溝通 事前準備 如果我沒記錯的話,組員都是從 Alpha Camp

[LeetCode] 961. N-Repeated Element in Size 2N Array

題目 In a array A of size 2N, there are N+1 unique elements, and exactly one of these elements is repeated N times. Return the element repeated N times. Note: 4 <= A.length <= 10000 0 <= A[i] < 10000 A.length is even 直覺解 構想: 因為陣列中的元素可能是 0,所以不能用正負號來紀錄數字是否出現過,也不能把陣列轉換成 linked list。 從 nums 的第一個元素開始檢查,把出現過的元素記錄下來。若發現有個數字已經出現過,就 return 該數字 javascript 實作: const repeatedNTimes = function(A) {    const seen = {}    let i = 0    while(i < A.length) {        if (!seen[A[i]]) {            seen[A[i]] = true        } else {             return A[i]        }         i++    } } 效能: Runtime: 72 ms, faster than 98.97% of JavaScript online submissions for N-Repeated Element in Size 2N Array. Memory Usage: 41.8 MB, less than 93.08% of JavaScript online submissions for N-Repeated Element in Size 2N Array. 犯過的低級錯誤: 把 seen[A[i]] 寫成 seen.[A[i]]

[LeetCode] #26. Remove Duplicates from Sorted Array

題目 Given a sorted array nums, remove the duplicates in-place such that each element appears only once and returns the new length. Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. 直覺解 構想: 從 nums 的最後一個元素開始檢查,如果他和前一個元素相同的話,就把當下這個元素刪掉。最後回傳 nums.length javascript 實作: const removeDuplicates = function(nums) {     for (let i = nums.length - 1; i > 0; i--) {         if (nums[i] === nums[i - 1]) {             nums.splice(i, 1)         }     }     return nums.length } 效能: Runtime: 100 ms, faster than 49.12% of JavaScript online submissions for Find Words That Can Be Formed by Characters. Memory Usage: 40.8 MB, less than 75.80% of JavaScript online submissions for Find Words That Can Be Formed by Characters. 看 Solution 的解 構想: 使用 i, j 兩個 pointer,i 負責指在沒有重複的數字上,j 則迭代 nums 中的每個元素。如果 j 有發現下一個不重複的數字,就把 i 的下一個數字改成「j 發現的那個數字」 javascript 實作: const removeDuplicates = function(nums) {  

[LeetCode] #287. Find the Duplicate Number

題目 Given an array of integers nums containing  n + 1 integers where each integer is in the range [1, n] inclusive. There is only one repeated number in nums , return this repeated number . You must solve the problem without modifying the array nums  and uses only constant extra space. 直覺解(未讀懂題目版) 構想: 計算出「1 + 2 + ... + (nums.length - 1)」的總和,再計算出 nums 中每個元素的總和,然後用後者減去前者,就能得到答案 javascript 實作: const findDuplicate = function(nums) {     if (nums.length === 2) { return nums[0] }     const factorial = (nums.length * (nums.length - 1) / 2)     const reducer = (accumulator, currentValue) => accumulator + currentValue     const sum = nums.reduce(reducer)     const repeatedNumber = sum - factorial     return repeatedNumber } 錯誤: 重複的那個數字,出現次數可能不只二次,所以這個方法不可行。 直覺解(已讀懂題目版,未挑戰 Follow up) 構想: 用 nums 紀錄數字是否出現過:迭代 nums 中的每個元素,如果當下的元素是 2 ,就用 nums 中第二個元素的值的正負號,紀錄 2 是否出現過。正的代表沒出現過,負的代表有出現過。(不符合「 without modifying the array」的限制) 例如, nums =

[LeetCode] #1160. Find Words That Can Be Formed by Characters

題目 You are given an array of strings words and a string chars. A string is good if it can be formed by characters from chars (each character can only be used once). Return the sum of lengths of all good strings in words. 直覺解 構想: 將陣列 words 中的每個元素拿出來,檢查裡面的每個字母是否有在 chars 裡。如果有在 chars 裡,要把 chars 裡相應的字母刪掉,以免重複使用相同的字母。 javascript 實作: const countCharacters = function(words, chars) {   let sumOfGoodStringLength = 0   words.forEach(word => {     let copyChars = chars     if (word.length > copyChars.length) { return }     for (let i = 0; i < word.length; i++) {       if (copyChars.includes(word[i])) {         copyChars = copyChars.replace(word[i], '')       } else {         return       }     }     sumOfGoodStringLength += word.length   })   return sumOfGoodStringLength } 效能: Runtime: 104 ms, faster than 87.15% of JavaScript online submissions for Find Words That Can Be Formed by Characters. Memory Usage: 46.2 MB, less than 78.15% of JavaScript o