preface
This week, I share a double pointer related algorithm problem. The author's level is limited. If you have any questions, please leave a message at the bottom of the article!
Key words: double pointer.
subject
Sum of three
Give you an array num containing n integers. Judge whether there are three elements a, b and c in num, so that a + b + c = 0? Please find all triples with sum 0 and no repetition.
Note: the answer cannot contain duplicate triples.
Example Input: nums = [-1,0,1,2,-1,-4] Output:[[-1,-1,2],[-1,0,1]]
Original question: https://leetcode-cn.com/problems/3sum
Solution 1 - brute force cracking
Traverse from scratch, first determine the first element, then traverse and try to combine with the second element, and then traverse and try the third element for each combination.
Each group of qualified combinations will be compared with the found combinations one by one. If they are repeated, they will be removed.
The time complexity of this method is of course quite high.
Time complexity: O(n^3)
Solution 2 - sorting + double pointer
The above brute force cracking method obviously has huge optimization space. We can use the double pointer method to solve this problem.
Specific flow of algorithm:
-
Special judgment: if the length len of the original array is less than 3, it will be returned directly
-
Sort arrays
-
Traverse the array from the beginning. The traversal condition is I < len-2 and num [i] is less than or equal to 0
-
If the current element nums[i] is the same as the previous element nums[i-1], skip to prevent duplicate results
-
Take the left pointer L as i+1 and the right pointer R as len-1. When the left boundary is less than the right boundary, execute the loop:
- If num [i] + num [l] + num [R] < 0, L=L+1. If num [l] = = num [L-1], l continues to move to the right to prevent duplication of results
- If num [i] + num [l] + num [R] > 0, R=R-1. If num [R] = = num [R + 1], R continues to move to the left to prevent repetition of results
- If num [i] + num [l] + num [R] = = 0, add the result set, and then L=L+1, R=R-1. At the same time, it is also necessary to prevent duplicate results
-
Code implementation:
class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { // Result: result set vector<vector<int>> result; // Gets the length of the original array int len = nums.size(); // Special judgment: if the length of the original array is less than 3, it will be returned directly if(len<3) return result; // Sort the original array first sort(nums.begin(), nums.end()); // Traverse the array from the beginning. The traversal condition is I < len-2 and num [i] < = 0 for(int i=0;i<len-2 && nums[i]<=0;i++){ // If the current element is the same as the previous element, skip to prevent duplicate results // Remember to limit the size of i, or the subscript will cross the boundary while(i>0 && i<len-1 && nums[i]==nums[i-1]) i++; // 50: L eft pointer, initialized to the current element + 1 position int L = i+1; // R: Right pointer, initialized to the end element position int R = len-1; // Start the loop to find the combination that meets the conditions. When the right pointer is less than or equal to the left pointer, jump out of the loop while(L<R){ if(nums[i]+nums[L]+nums[R] == 0){ // If the combination meets the conditions, it is added to the result set result.push_back({nums[i], nums[L], nums[R]}); // Move left pointer to right L++; while(L>0 && L<len-1 && nums[L] == nums[L-1]){ // If the left pointer moves to the right and finds that the element is the same as the previous element, continue to move to the right to prevent duplicate results // Also remember to limit the size of L here, otherwise the subscript will cross the boundary L++; } // The right pointer moves to the left R--; while(R>0 && R<len-1 && nums[R] == nums[R+1]){ // If the right pointer moves to the left and finds that the element is the same as the next element, continue to move to the left to prevent duplicate results // Also remember to limit the size of R here, otherwise the subscript will cross the boundary R--; } }else if(nums[i]+nums[L]+nums[R] < 0){ // If the combined sum is less than 0 // Adjust the left pointer to move to the right L++; while(L>0 && L<len-1 && nums[L] == nums[L-1]){ // If the left pointer moves to the right and finds that the element is the same as the previous element, continue to move to the right to prevent duplicate results L++; } }else if(nums[i]+nums[L]+nums[R] > 0){ // If the combined sum is greater than 0 // Adjust the right pointer to move to the left R--; while(R>0 && R<len-1 && nums[R] == nums[R+1]){ // If the right pointer moves to the left and finds that the element is the same as the next element, continue to move to the left to prevent duplicate results R--; } } } } // Finally, the result set is returned return result; } };
Time complexity:
Sorting time complexity O(Nlog2(N))
Pass through group O(n)
Double pointer traversal O(n)
Overall time complexity O(Nlog2(N))+O(n)*O(n), i.e. O(n^2).
Space complexity: O(1)