目录
11. 盛最多水的容器 - 力扣(Leetcode)
思路:
15. 三数之和 - 力扣(Leetcode)
思路
这是典型的双指针解法,使用left指针指向数组的0下标,right指针指向数组的最后一个下标,写出盛水容积的关系式:Volume =min(height[left],height[right]) * (right-left),维护一个最大的容积maxVolume,maxVolume = max(maxVolume,volume),之后指针需要移动,移动的策略就是:
哪个指针对应的高度值小,移动哪一个指针,因为容积的约束条件是小的哪个指针对应的值。
python
class Solution:
def maxArea(self, height: List[int]) -> int:
# 双指针解法
# 边界
n = len(height)
if n < 2:return 0
maxVolume = 0
left,right = 0,n-1
while left < right:
maxVolume = max(maxVolume,min(height[left],height[right]) * (right-left))
if height[left] > height[right]:right -= 1
else:left += 1
return maxVolume
c++
class Solution {
public:
int maxArea(vector& height) {
//双指针问题
int maxVol = 0;
int left = 0,right = height.size()-1;
while (left < right){
maxVol = max(maxVol,min(height[left],height[right]) * (right - left));
if (height[left] < height[right]) left++;
else right--;
}
return maxVol;
}
};
第一道题太简单了,今天多做一道题。
这个问题的初始解法是使用三重循环遍历,但是这样时间复杂度是O(n^3),这样不好,写出来面试官也会让你优化的,所以这里使用的是排序+双指针的办法降低复杂度。
找一个三元组,三元组的下标不能相同,就是不能重复使用同一个元素,且三个元素的和为零。
这里可以先排序,排序之后遍历数组,遍历的元素作为三元组的第一个元素,之后使用双指针,left指针指向第一个元素下标+1的元素,right指针指向数组的最后一个元素。看双指针指向的元素的和 + 第一个元素之后和0的关系,如果三者的和比0小,(暂时固定第一个元素,寻找第二个和第三个元素),left++,比0大,right--。
因为要求答案中不能出现重复的三元组,所以记得去重。
python
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# 预判
n = len(nums)
if n < 3:return []
nums.sort() # 排序之后数组才有规律,才有意义
# 初始化
ans = list()
for i in range(n):
if nums[i] > 0:return ans
if i > 0 and nums[i] == nums[i-1]:continue # 去重
# 双指针
left ,right = i+1,n-1
while left < right:
if left < right and nums[left] + nums[right] < -nums[i]:left += 1
elif left < right and nums[left] + nums[right] > -nums[i]: right -= 1
else:
ans.append([nums[i],nums[left],nums[right]])
left += 1
right -= 1
# 去重
while left < right and nums[left] == nums[left-1]:left += 1
while left < right and nums[right] == nums[right+1]: right -= 1
return ans
c++
class Solution {
public:
vector> threeSum(vector& nums) {
//排序 + 双指针
int n = nums.size();
if (n < 3) return {};
sort(nums.begin(),nums.end());
vector> ans;
for (int i = 0;i < n;i++){
if (nums[i] > 0) return ans;
if (i > 0 && nums[i] == nums[i-1]) continue;
int left = i+1,right = n-1;
while (left < right){
if (nums[left] + nums[right] < -nums[i]) left++;
else if (nums[left] + nums[right] > -nums[i]) right--;
else{
ans.push_back(vector{nums[i],nums[left],nums[right]});
left++;
right--;
while (left < right && nums[left] == nums[left-1]) left++;
while (left < right && nums[right] == nums[right+1]) right--;
}
}
}
return ans;
}
};