LeetCode #1~6
LeetCode practice using C++ by Visual Studio Code @ubuntu 16.04
#1 Two Sum Easy
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Solution 1: 暴力解 -> T(n) = O(n²),S(n) = O(1)
Solution 2: 以空間換取時間,建HashMap -> T(n) = O(n),S(n) = O(n)
- 用HashMap建立數字與座標的映射
- 若target減去當前數字存在於HashMap中即為解
hint: unordered_map<int, int> hmap;
#2 Add Two Numbers Medium
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contains a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
- 兩個鍵結依序相加生成新節點放到新鍵結之後
- 兩個鍵結長度可能不同 -> 需判斷鍵結若為空,則取 0,否則取節點值
- 用一個cursor指向新鍵結的最後一個節點來紀錄目前處理位置
- 避免兩個鍵結同時為空 -> 需先建立一個dummy節點
- 最後需要特別處理最高位的進位,carry若為 1 -> 建立一個值為 1 的節點
hint: ListNode *ans = new ListNode(-1);
迴圈寫法: T(n) = O(max(m,n)),S(n) = O(max(m,n))
遞迴寫法: T(n) = O(max(m,n)),S(n) = O(max(m,n))
Follow up:
#2.5
You have two numbers represented by a linked list, where each node contains a single digit. The digits are stored in reverse order, such that the 1’s digit is at the head of the list. Write a function that adds the two numbers and returns the sum as a linked list.
EXAMPLE
Input: (7-> 1 -> 6) + (5 -> 9 -> 2).That is, 617 + 295.
Output: 2 -> 1 -> 9.That is, 912.
FOLLOW UP
Suppose the digits are stored in forward order. Repeat the above problem.
EXAMPLE
Input: (6 -> 1 -> 7) + (2 -> 9 -> 5).That is, 617 + 295.
Output: 9 -> 1 -> 2.That is, 912.
- 翻轉鍵結相加再翻轉
- 補0到相同長度用遞迴方式處理
#3 Longest Substring Without Repeating Characters Medium
Given a string, find the length of the longest substring without repeating characters.
Solution 1: T(n) = O(n²),S(n) = O(1)
- 不使用HashMap比較暴力的解法
- 使用兩個index,i 用來遍歷字串,j 用來檢查是否有重複的字母
- 若遇到重複字母,則更新 j 的起始點
- 若無重複則累加,找出最長的子字串長度
Solution 2: T(n) = O(n),S(n) = O(min(m,n))
- 建立一個HashMap紀錄字母最後出現的位置
- 使用一個sliding window,使window在無重複字母的情形下盡可能擴展
- 用一個index紀錄window左邊界的前一個位置,因此default為 -1
- 若遇到相同字母且該字母在window中,更新index
#4 Median of Two Sorted Arrays Hard
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.
Solution 1: T(n) = O(m+n),S(n) = O(m+n)
重新排序合併成一個新的sorted array,排序到中位數的位置
- 建立一個新的vector,用兩個index分別從兩個array取值,從小到大放進新建的vector,取到中位數的位置
- 若有一個array先被取完,將它最後一個值設為比另一個array的最大值多 1 (或設為整數最大值),以避免再來取這個array
- 需判斷總數為奇數或偶數時中位數的取法不同
- 需另外處理兩個或其中一個array為空的情形
Solution 2: T(n) = O(m+n),S(n) = O(m+n)
- 改善solution 1,不用去考慮數列個數為偶數或奇數
- 取第 (m+n+1)/2 和第 (m+n+2)/2 個數字求其平均值
- 注意第 n 個數字的index是 n–1
Solution 3: T(n) = O(log(m+n)),S(n) = O(1)
對中位數的index使用二分法遞迴找出中位數的值
- 假設所求為第 k 個數字,用兩個變數 i, j 來紀錄兩個數列的起始位置
- 若起始位置大於數列長度,表示該數列已全數淘汰 -> 直接找另一個數列
- k=1時,表示要取第一個數字 -> 取兩數列起始位置上的較小的那個
- 分別在兩個數列中查找第 k/2 個數字
- 若不存在 -> 淘汰另一個數列的前 k/2 個數字
- 比較兩數列第 k/2 個數字的大小,淘汰較小的數列的前 k/2 個數字
- 更新 k -> 遞迴去淘汰兩數列中 k/2 個較小的數字
Solution 4: T(n) = O(log(min(m, n))),S(n) = O(1)
迭代形式的二分搜索法
#5 Longest Palindromic Substring Medium
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Solution 1: T(n) = O(n²),S(n) = O(1)
- 從第二個字母開始,當作中心往兩邊擴展檢查兩邊字母是否一樣
- 一樣的話就更新輸出回文字串的起始index以及長度
- 長度為偶數的回文字串 -> 先檢查兩相鄰字母是否一樣
- 一樣的話讓檢查回文的左邊界index先減 1
Solution 2: T(n) = O(n²),S(n) = O(1)
改善solution 1,將步驟3的檢查兩相鄰字母合併到checkPalindrome中
Solution 3: T(n) = O(n²),S(n) = O(n²)
Dynamic Programming的作法
- 宣告一個二維數列isPalindrome來紀錄在區間 [i, j] 內是否為回文字串
- 需特別處理空字串,否則數列isPalindrome會宣告失敗
- 規則如下:
a. 當 i = j,表示只有一個字母,必為回文
b. 當 i = j+1,為兩相鄰字母,若兩字母相等則為回文
c. 當 i > j+1,不相鄰兩字母若相等,且區間 [i-1, j+1] 為回文則為回文
Solution 4: T(n) = O(n),S(n) = O(n)
Manacher’s Algorithm
#6 ZigZag Conversion Medium
The string "PAYPALISHIRING"
is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N
A P L S I I G
Y I R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string s, int numRows);
Solution 1: T(n) = O(n),S(n) = O(n)
- 以一條直線加一條斜線為一個loop,每個loop會跳過jump個字母
- jump的規律可以觀察出來是numRows*2–2 -> loop = length/jump
- 先考慮落在直線上的字母,在原字串的index應為j*jump+i
- 再補上其他在斜線上的字母,在原字串的index應為index+jump-2*i
- 處理取值範圍超過字串長度的狀況
- 處理numRows為 1 造成jump為 0 的狀況
Solution 2: T(n) = O(n),S(n) = O(n)
改善solution 1,j 為直線上字母的位置 -> 斜線上字母index = j+jump-2*i
Solution 3: T(n) = O(n),S(n) = O(n)
- 建一個大小為numRows的字串vector,vector的index表示第幾個row
- 兩個for loop,往下走和往上走,按順序將字母丟入對應row子字串中
- 最後將vector中的子字串按vector的index順序接起來即為所求