leetcode15三数之和
算法思路:这道题我开始想到就是要固定一个数,然后要用双指针来做,但是两个指针的移动覆盖所有的数据,这样如何更新我没有想明白。
这是道好题
正确的解法应该是先将数组排序,遍历数组,固定一个数,再用双指针从这个数的右边开始遍历。如果将双指针从数组的起点和端点开始遍历,会得到很多重复的满足条件的组,因为考虑了重复的组别**。所以这里要能想到将双指针从这个数的右边开始遍历就会避免考虑重复的情况而且能够覆盖到所有的情况**,我画了一个简图解释一下。
从最底下的5开始看,我们先遍历5右边的,然后从加入4后,重新遍历4以后的情况。重复这样一直到1,我们发现所有的情况都覆盖到了,并且不会考虑重复的组。
除此之外 算法还值得注意的地方在于:
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
list = []
if len(nums) < 3:
return []
nums.sort()
for i in range(len(nums)):
if nums[i] >0:
break
low = i+1
high = len(nums)-1
if i > 0 and nums[i] == nums[i-1]: #避免重复的组
continue
while(low < high):
value = nums[i] + nums[low] + nums[high]
if value == 0:
list.append([nums[i], nums[low], nums[high]])
low += 1
high -= 1
while(low < high and nums[low] == nums[low-1]): # 避免重复的组
low += 1
while(high > low and nums[high] == nums[high+1]): # 避免重复的组
high -= 1
if value > 0:
high -= 1
if value < 0:
low += 1
return list
leectcode16最接近三数之和
算法思路:这道题和三数之和思路与很像,唯一的不同点就是要在遍历的过程中要记录和target最接近的三数之和,如何衡量接近,用绝对值就可以。
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
length = len(nums)
if length < 3:
return nums
count = 9223372036854775807
nums.sort()
for i in range(length-2):
low = i+1
high = length-1
if i > 0 and nums[i] == nums[i-1]:
i += 1
continue
while low < high:
value = nums[i] + nums[low] + nums[high]
if (abs(value - target) < abs(count - target)):
count = value
if value == target:
return target
else:
if value > target:
high -= 1
if value < target:
low += 1
return count
leetcode18四数之和
算法思路:和三数之和基本是一样的,
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
length = len(nums)
list = []
if length < 4:
return list
nums.sort()
for i in range(length-3):
left = i+1
if i > 0 and nums[i] == nums[i-1]: #这里要注意i > 0的条件
i += 1
continue
for j in range(left, length-2):
if j > left and nums[j] == nums[j-1]: # 同样这里要注意j > left的条件
j += 1
continue
middle = j+1
right = length - 1
while(middle < right):
value = nums[i] + nums[j] +nums[middle] + nums[right]
if target == value:
list.append([nums[i], nums[j], nums[middle], nums[right]])
middle += 1
right -= 1
while(middle < right and nums[middle] == nums[middle-1]):
middle += 1
while(middle < right and nums[right] == nums[right +1]):
right -= 1
elif target < value:
right -= 1
else:
middle += 1
return list
leetcode11乘最多水的容器
算法思路,如果能想到用双指针法从数组的两边开始检索,当两指针指向的矩形两边,移动较短的两边可能增加矩形的面积,而移动较长的边注定会减少矩形的面积。这道题就解决了
class Solution:
def maxArea(self, height: List[int]) -> int:
low = 0
high = len(height) -1
max_Area = 0
while(low < high):
# reauslt = height[low] if height[low] < height[high] else height[high]
max_Area = max(max_Area, min(height[low],height[high])*(high-low))
if height[low] < height[high]:
low += 1
else:
high -= 1
return max_Area
leetcode31下一个排列
这道题我真的要爆粗了,用评论中的一句话来说”就是这道题的每个字我都认识,连起来我就不懂了“。
我说下我理解的题意,所谓全排列就是要从从数组的右边往左边开始遍历找第一组 n u m s [ i ] > n u m s [ i − 1 ] nums[i] > nums[i-1] nums[i]>nums[i−1]。找到之后就开始在这个位置往右边遍历,然后直到找到最小的大于 n u m s [ i − 1 ] nums[i-1] nums[i−1]的数 n u m s [ j ] nums[j] nums[j](在我的code里面这个数是 n u m s [ i n d e x _ l o w ] nums\lbrack index\_low\rbrack nums[index_low]),交换 n u m s [ i − 1 ] nums[i-1] nums[i−1]和 n u m s [ j ] nums[j] nums[j]。此时我们还要保证包括 n u m s [ i ] nums[i] nums[i]到 n u m s [ l e n g h t h − 1 ] nums[lenghth-1] nums[lenghth−1]的元素按升序排列。
最后如果没有找到这一对数字说明整个序列已经按降序排列好了,直接反转就行。
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
""" Do not return anything, modify nums in-place instead. """
length = len(nums)
flag = 0
for i in range(length-1, 0, -1):
if nums[i] > nums[i-1]:
flag = 1
index_low = i
# 注意下面这个判断条件 中不要写成nums[index_low] >= nums[i-1]!!
while(index_low < length and nums[index_low] > nums[i-1]):
index_low += 1
tmp = nums[index_low-1]
nums[index_low-1] = nums[i-1]
nums[i-1] = tmp
i_right = nums[i::]
i_right.sort()
for j in range(len(i_right)):
nums[i] = i_right[j]
i += 1
break
if flag == 0:
nums.reverse()