【LeetCode】雙指針 two_pointers(共47題)

【3】Longest Substring Without Repeating Characters html

【11】Container With Most Water 算法

 

【15】3Sum (2019年2月26日)數組

給了一個亂序的數組,返回一個結果數組,數組裏面每一個元素是一個三元組, 三元組的和加起來爲0。app

題解:先固定第一個數,而後後面兩個數的控制用夾逼定理,2 pointers 來解。 ide

 1 class Solution {
 2 public:
 3     vector<vector<int>> threeSum(vector<int>& nums) {
 4         const int n = nums.size();
 5         vector<vector<int>> res;
 6         if (nums.size() < 3) {return res;}
 7         sort(nums.begin(), nums.end());
 8         for (int i = 0 ; i < n; ) {
 9             int left = i + 1, right = n - 1;
10             while (left < right) {
11                 int sum = nums[i] + nums[left] + nums[right];
12                 if (sum == 0) {
13                     res.push_back(vector<int>{nums[i], nums[left], nums[right]});
14                     ++left, --right;
15                     while (left < right && nums[left] == nums[left-1]) { ++left; } 
16                     while (left < right && nums[right] == nums[right+1]) { --right; }
17                 } else if (sum < 0) {
18                     ++left;
19                     while (left < right && nums[left] == nums[left-1]) { ++left; } 
20                 } else {
21                     --right;
22                     while (left < right && nums[right] == nums[right+1]) { --right; }
23                 }
24             }
25             ++i;
26             while (i < n && nums[i] == nums[i-1]) {++i;}
27         }
28         return res;
29     }
30 };
View Code

 

【16】3Sum Closest (2019年2月26日)oop

 

【18】4Sum ()優化

【19】Remove Nth Node From End of List google

【26】Remove Duplicates from Sorted Array spa

【27】Remove Element 3d

【28】Implement strStr() 

【30】Substring with Concatenation of All Words 

【42】Trapping Rain Water 

【61】Rotate List 

【75】Sort Colors 

 

【76】Minimum Window Substring (2019年1月13日,算法羣,第一次寫,須要複習)

給了兩個字符串 S 和 T, 在S中求一個最短子串,這個字串須要包含 T 中的全部字母。

題解: sliding window, (有兩種,窗口大小可變和窗口大小不變的)。用 2 pointers 模擬窗口。時間複雜度是 O(N)。用一個 hash-map mp 記錄 t 中的字母頻次。用一個 count 變量記錄已經知足了的 字母數量。當 mp.size() == count 的時候就能夠考慮縮小窗口。https://www.youtube.com/watch?v=9qFR2WQGqkU

 1 class Solution {
 2 public:
 3     string minWindow(string s, string t) {
 4         const int ssize = s.size(), tsize = t.size();
 5         if (ssize < tsize) {
 6             return "";
 7         }
 8         unordered_map<char, int> mp;
 9         for (auto c : t) {
10             mp[c]++;
11         }
12         int slow = 0, fast = 0, minLen = INT_MAX, start = 0, count = 0;
13         for (; fast < ssize; ++fast) {
14             char c = s[fast];
15             if (mp.find(c) == mp.end()) {
16                 continue;
17             }
18             mp[c]--;
19             if (mp[c] == 0) { count++; }
20             while (count == mp.size()) {
21                 if (fast - slow + 1 < minLen) {
22                     minLen = fast - slow + 1;
23                     start = slow;
24                 }
25                 char c1 = s[slow++];
26                 if (mp.find(c1) == mp.end()) { continue; }
27                 mp[c1]++;
28                 if (mp[c1] == 1) {
29                     count--;
30                 }
31             }
32         }
33         return minLen == INT_MAX ? "" : s.substr(start, minLen);
34     }
35 };
View Code

 

【80】Remove Duplicates from Sorted Array II 

【86】Partition List 

【88】Merge Sorted Array 

【125】Valid Palindrome 

【141】Linked List Cycle 

【142】Linked List Cycle II 

【159】Longest Substring with At Most Two Distinct Characters 

【167】Two Sum II - Input array is sorted 

 

【209】Minimum Size Subarray Sum (2019年1月11日,算法羣)

給了 n 個正整數 nums 數組,和一個正整數 s,要求返回一個最短連續子數組的長度,使得這個子數組的和大於等於s。

follow-up 是 若是想出了 O(n)  的作法,能不能想出 O(nlogn)  的作法。

題解:O(N)  的作法是 2 pointers, O(nlogn) 的作法是 前綴和 + 二分

 1 class Solution {
 2 public:
 3     int minSubArrayLen(int s, vector<int>& nums) {
 4         const int n = nums.size();
 5         int p1 = 0, p2 = 0;
 6         int ans = n + 1, cur_sum = 0;
 7         while (p1 <= p2 && p2 < n) {
 8             cur_sum += nums[p2];
 9             while (p1 < p2 && cur_sum - nums[p1] >= s) {
10                 cur_sum -= nums[p1];
11                 ++p1;
12             }
13             if (cur_sum >= s) {
14                 ans = min(p2 - p1 + 1, ans);
15             }
16             ++p2;
17         }
18         return ans == n + 1 ? 0 : ans;
19     }
20 };
View Code

  

【234】Palindrome Linked List 

 

【259】3Sum Smaller (2019年2月26日,谷歌 tag)

給了一個亂序的數組,能不能從中找出三個數,nums[i], nums[j], nums[k] 他們三個想加的和小於target,返回這樣三個數的個數。要求時間複雜度是O(N^2)

題解:我想出來的 O(n^2) 的解法是用個map輔助,實時更新map。可是這題的標準解法是先sort,而後先選出一個數,而後剩下兩個數用夾逼定理。

 1 class Solution {
 2 public:
 3     int threeSumSmaller(vector<int>& nums, int target) {
 4         const int n = nums.size();
 5         sort(nums.begin(), nums.end());
 6         int res(0);
 7         for (int i = 0; i < n; ++i) {
 8             res += twoSumSmaller(nums, i + 1, target - nums[i]);
 9         } 
10         return res;
11     }
12     int twoSumSmaller(vector<int>& nums, int start, int target) {
13         int left = start, right = nums.size() - 1;
14         int res(0);
15         while (left < right) {
16             int sum = nums[left] + nums[right];
17             if (sum < target) {
18                 res += right - left; //包含nums[left]的全部可能解
19                 ++left;
20             } else {
21                 --right;
22             }
23         }
24         return res;
25     }
26 };
View Code

 

【283】Move Zeroes 

 

【287】Find the Duplicate Number 

 

【344】Reverse String (2018年12月3日,第一次review,ko)

逆序一個字符串。

題解:見string分類:http://www.javashuo.com/article/p-daxixbpb-mq.html

 

【345】Reverse Vowels of a String (2018年12月4日,第一次review,ko)

逆序一個字符串的元音字母。

題解:見string分類:http://www.javashuo.com/article/p-daxixbpb-mq.html

 

【349】Intersection of Two Arrays (2018年11月6日,算法羣相關題)

hash-table 裏面有這題,我就不重複寫了。hash-table:http://www.javashuo.com/article/p-mjknibky-mq.html

 

【350】Intersection of Two Arrays II (2018年11月6日,算法羣)

hash-table 裏面有這題,我就不重複寫了。hash-table:http://www.javashuo.com/article/p-mjknibky-mq.html

 

【360】Sort Transformed Array 

判斷一個循環數組是否是裏面是否是含有環,circular array. 

If a number k at an index is positive, then move forward k steps. Conversely, if it’s negative (-k), move backward k steps. Since the array is circular, you may assume that the last element’s next element is the first element, and the first element’s previous element is the last element.

Determine if there is a loop (or a cycle) in nums. A cycle must start and end at the same index and the cycle’s length > 1. Furthermore, movements in a cycle must all follow a single direction. In other words, a cycle must not consist of both forward and backward movements.
Could you solve it in O(n) time complexity and O(1) extra space complexity?

題解:快慢指針。這個題目只能沿着一個方向走,因此咱們須要判斷一下,當前的方向是否是一開始的方向相同,也就是快指針每走一步都要判斷一下出發點的數字是否是相同的符號,也就是while循環的部分。

當快慢指針相遇的時候,須要判斷一下環的大小是否是1個結點,若是是的話這樣是。若是大於一個結點,則返回true。

 1 class Solution {
 2 public:
 3     bool circularArrayLoop(vector<int>& nums) {
 4         const int n = nums.size();
 5         for (int i = 0; i < nums.size(); ++i) {
 6             if (!nums[i]) {continue;}
 7             int slow = i, fast = i;
 8             while (nums[fast] * nums[i] > 0 && nums[getNext(fast, nums)] * nums[i] > 0) {
 9                 slow = getNext(slow, nums), fast = getNext(getNext(fast, nums), nums);
10                 if (slow == fast) {
11                     if (getNext(slow, nums) != slow) { return true; }
12                     else {break;}
13                 }
14             }
15             /*
16             //把走過的slow set成爲不能走的狀態
17             slow = i;
18             while (nums[slow] * nums[i] > 0) {
19                 nums[slow] = 0;
20                 slow = getNext(slow, nums);
21             }
22             */
23         }
24         return false;
25     }
26     int getNext(int cur, vector<int>& nums) {
27         const int n = nums.size();
28         int res = (nums[cur] + cur) % n;
29         return res < 0 ? res + n : res;
30     }
31 };
View Code

 

【487】Max Consecutive Ones II (2018年11月27日)(2019年3月3日更新)

給了一個0/1數組,問若是最多隻能把一個 0 變成 1 的話,那麼這個數組裏面最長的連續 1 有幾個?

題解:我是對於每個 0 都求出了它前面連續 1 的個數 和後面連續 1 的個數。而後再遍歷一邊原數組,求長度,比較。注意若是全 1 的狀況須要考慮。

discuss裏面有更好的解法,不用多兩個數組。

 1 class Solution {  2 public:  3     int findMaxConsecutiveOnes(vector<int>& nums) {  4         const int n = nums.size();  5         vector<int> pre(n, -1), next(n, -1);  6         int cnt = 0;  7         for (int i = 0; i < n; ++i) {  8             if (nums[i] == 0) {  9                 pre[i] = cnt; 10                 cnt = 0; 11             } else { 12                 cnt++; 13  } 14  } 15         cnt = 0; 16         for (int i = n-1; i >= 0; --i) { 17             if (nums[i] == 0) { 18                 next[i] = cnt; 19                 cnt = 0; 20             } else { 21                 cnt++; 22  } 23  } 24         int ret = 0; 25         cnt = 0; 26         for (int i = 0; i < n; ++i) { 27             if (nums[i] == 0) { 28                 ret = max(ret, pre[i] + next[i] + 1); 29                 cnt = 0; 30             } else { 31                 cnt++; 32                 ret = max(cnt, ret); 33  } 34  } 35         return ret; 36  } 37 };
View Code

follow-up:What if the input numbers come in one by one as an infinite stream? In other words, you can't store all numbers coming from the stream as it's too large to hold in memory. Could you solve it efficiently?

2019年3月3日更新,這題和 1004 這週週賽題如出一轍,這個是最多能變一個1,1004是是最多能變 k 個 1。解法是 sliding window with 2 pointers。

 1 class Solution {
 2 public:
 3     int findMaxConsecutiveOnes(vector<int>& nums) {
 4         const int n = nums.size();
 5         int start = 0, cnt = 0, res = 0;
 6         for (int i = 0; i < n; ++i) {
 7             if (nums[i] == 0) {cnt++;}
 8             while (cnt > 1) {
 9                 if (nums[start] == 0) {--cnt;}
10                 ++start;
11             }
12             res = max(res, i - start + 1);
13         }
14         return res;
15     }
16 };
View Code

 

【524】Longest Word in Dictionary through Deleting 

【532】K-diff Pairs in an Array 

【567】Permutation in String 

【632】Smallest Range 

 

【713】Subarray Product Less Than K (2019年2月11日)

給了一個數組,返回有多少子數組的乘積小於K。

題解:暴力解法O(N^2),2 pointers + sliding window 能夠優化到 O(N). 每一步都往移動一個end指針,若是當前的乘積大於等於k了,就往前移動begin指針。計算包含當前end的子數組個數。

 1 class Solution {
 2 public:
 3     int numSubarrayProductLessThanK(vector<int>& nums, int k) {
 4         const int n = nums.size();
 5         int begin = 0, end = 0, multi = 1, res = 0;
 6         while (end < n) {
 7             multi = multi * nums[end];
 8             while (begin < end && multi >= k) {
 9                 multi /= nums[begin];
10                 ++begin;
11             }
12             if (multi < k) {
13                 res += (end - begin + 1);
14             }
15             ++end;
16         }
17         return res;
18     }
19 };
View Code

 

【723】Candy Crush 

【763】Partition Labels 

【826】Most Profit Assigning Work

 

【828】Unique Letter String (H)(2019年3月5日)

A character is unique in string S if it occurs exactly once in it.

For example, in string S = "LETTER", the only unique characters are "L" and "R".

Let's define UNIQ(S) as the number of unique characters in string S

For example, UNIQ("LETTER") =  2.

Given a string S with only uppercases, calculate the sum of UNIQ(substring) over all non-empty substrings of S.

If there are two or more equal substrings at different positions in S, we consider them different.

Since the answer can be very large, return the answer modulo 10 ^ 9 + 7.

Example 1:
Input: "ABC"
Output: 10
Explanation: All possible substrings are: "A","B","C","AB","BC" and "ABC".
Evey substring is composed with only unique letters.
Sum of lengths of all substring is 1 + 1 + 1 + 2 + 2 + 3 = 10

Example 2:
Input: "ABA"
Output: 8
Explanation: The same as example 1, except uni("ABA") = 1.

Note: 0 <= S.length <= 10000.

題解:hanson solution: https://leetcode.com/problems/unique-letter-string/discuss/ 

 1 class Solution {
 2 public:
 3     const int mod = 1e9+7;
 4     int uniqueLetterString(string S) {
 5         vector<vector<int>> dp(26, vector<int>(2, -1));
 6         int res = 0;
 7         const int n = S.size();
 8         for (int i = 0; i < n; ++i) {
 9             int idx = S[i] - 'A';
10             res = (res + (dp[idx][1] - dp[idx][0]) * (i - dp[idx][1])) % mod;
11             dp[idx][0] = dp[idx][1];
12             dp[idx][1] = i;
13         }
14         for (int i = 0; i < 26; ++i) {
15             res = (res + (dp[i][1] - dp[i][0]) * (n - dp[i][1])) % mod;
16         }
17         return res;
18     }
19 };
View Code

 

【838】Push Dominoes 

【844】Backspace String Compare 

【845】Longest Mountain in Array 

【881】Boats to Save People

相關文章
相關標籤/搜索