前言:
1. 兩數之和
本來不想做的,無聊點開題解才發現竟然不是簡單的 A + B Problem。
方法一:暴力枚舉
1 class Solution { 2 public: 3 vector<int> twoSum(vector<int>& nums, int target) { 4 int n = nums.size(); 5 for (int i = 0; i < n - 1; i++) 6 for (int j = i + 1; j < n; j++) 7 if (nums[i] + nums[j] == target) 8 return {i, j}; 9 return {}; 10 } 11 };
注意:L9 的 return {} 不能省略,儘管題目說明了不會存在沒有結果的情況,但對於編譯器而言則必須要求在所有情況下都有返回值。
方法二:哈希表
由於答案對是唯一的,我們可以只掃描一次,用 target 減去當前值 nums[i],再判斷 nums 中是否有餘下的數。由於數據範圍遠大於數據量,採用哈希表可節省大量空間。在 C++ 中一般使用 map 實現哈希表。
1 class Solution { 2 public: 3 vector<int> twoSum(vector<int>& nums, int t) { 4 int n = nums.size(); 5 map<int, int> mp; 6 for (int i = 0; i < n; i++) { 7 auto it = mp.find(t - nums[i]); 8 if (it != mp.end()) 9 return {it -> second, i}; 10 mp[nums[i]] = i; 11 } 12 return {}; 13 } 14 };
2. 兩數相加
本質上考察鏈表的處理。
1 class Solution { 2 public: 3 ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { 4 int c = 0; 5 ListNode *h = NULL, *t = NULL; 6 while (l1 || l2) { 7 int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + c; 8 if (!h) 9 h = t = new ListNode(sum % 10); 10 else { 11 t->next = new ListNode(sum % 10); 12 t = t->next; 13 } 14 c = sum / 10; 15 if (l1) 16 l1 = l1->next; 17 if (l2) 18 l2 = l2->next; 19 } 20 if (c > 0) 21 t->next = new ListNode(c); 22 return h; 23 } 24 };
3. 無重複字符的最長子串
方法:雙指針法(LC官方寫的是滑動窗口)
設置左指針和右指針,右指針依次向右移動,如果指向字符之前出現在某個位置,且該位置在左指針的左側,則說明爲了維持無重複字符,則左指針需要跳到該位置的後一個位置;
所以這個過程中需要維護一個數組 a,a[i] 表示字符 i 上次出現的位置。兩個指針在移動過程中,其間的區間大小一直在變化,而變化過程中的最大值即爲答案。
(官方的題解的左指針是依次向右移動而非跳躍的,大概是因爲使用的 set,這樣相當於用更多時間換取了更少空間)
1 const int N = 130; 2 3 class Solution { 4 public: 5 int lengthOfLongestSubstring(string s) { 6 int l = s.length(), h = 0, t = 0, ans = 0, a[N]; 7 memset(a, -1, sizeof(a)); 8 while (t < l) { 9 if (a[s[t]] != -1) 10 h = max(h, a[s[t]] + 1); 11 a[s[t]] = t; 12 ans = max(ans, t - h + 1); 13 t++; 14 } 15 return ans; 16 } 17 };