文章目录
两数之和(7.21)
执行用时:3148ms
自己写的代码:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
n = len(nums)
for i in range(n):
for j in range(i+1,n):
if nums[i] + nums[j] == target:
return [i,j]
官方代码:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashtable = dict()
for i, num in enumerate(nums):
if target - num in hashtable:
return [hashtable[target - num], i]
hashtable[nums[i]] = i
return []
盛最多水的容器(7.22 难度中等)
面积取决于短板。①因此即使长板往内移动时遇到更长的板,矩形的面积也不会改变;遇到更短的板时,面积会变小。②因此想要面积变大,只能让短板往内移动(因为移动方向固定了),当然也有可能让面积变得更小,但只有这样才存在让面积变大的可能性
class Solution:
def maxArea(self, height: List[int]) -> int:
l, r = 0, len(height) - 1
ans = 0
while l < r:
area = min(height[l], height[r]) * (r - l)
ans = max(ans, area)
if height[l] <= height[r]:
l += 1
else:
r -= 1
return ans
删除有序数组中的重复项 (7.22 简单)
思考:
还是利用双指针
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
n = len(nums)
fast = slow = 1
while fast < n:
if nums[fast] != nums[fast - 1]:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
搜索插入位置(7.23)
这道题比较简单
自己写的代码:
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
n = len(nums)
minq = min(nums)
maxq = max(nums)
if target < minq:
return 0
if target > maxq:
return n
for i in range(n):
if nums[i] == target:
return i
if i < n-1 and nums[i] < target and target < nums[i+1]:
return i+1
官方代码:二分法
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
n = len(nums)
left = 0
right = n - 1
ans = n
while left <= right:
mid = (left+right)//2
if target <= nums[mid]:
ans = mid
right = mid -1
else:
left = mid + 1
return ans
移除元素(7.24 简单)
思考:
这道数组题目也是利用双指针
自己
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
n = len(nums)
j = 0
for i in range(n):
if nums[i] != val:
nums[j] = nums[i]
j = j + 1
return j
加一(7.24 简单)
思考1:
考虑到最后一位是9的情况了,但是没有考虑到列表最后几位都是9的情况。
思考2:
当末尾几位都是9的时候,只需要找出第一位不为9的数字,将其加1,后面的数字全部变成0即可。
当全部都是9的时候,列表第一个数字为1,其他均为0。
不能用转换成数字然后加了1之后再转换成数组的想法,会溢出的。
官方代码:
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
n = len(digits)
for i in range(n - 1, -1, -1):
if digits[i] != 9:
digits[i] += 1
for j in range(i + 1, n):
digits[j] = 0
return digits
# digits 中所有的元素均为 9
return [1] + [0] * n
合并两个有序数组(7.25)
思考:
官方算法
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
sorted = []
p1, p2 = 0, 0
while p1 < m or p2 < n:
if p1 == m:
sorted.append(nums2[p2])
p2 += 1
elif p2 == n:
sorted.append(nums1[p1])
p1 += 1
elif nums1[p1] < nums2[p2]:
sorted.append(nums1[p1])
p1 += 1
else:
sorted.append(nums2[p2])
p2 += 1
nums1[:] = sorted
存在重复元素(7.25)
思考1:
比较去重之后和去重之前的两个列表长度
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
return len(nums) != len(set(nums))
思考2:
先排序,后判断相邻位置的元素是否相等。
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
if len(nums) == 1:
return False
nums.sort()
for i in range(len(nums)-1):
if nums[i] == nums[i+1]:
return True
return False
存在重复数据2(7.25)
思考:
前面排序的方法就用不了了。
class Solution:
def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
s = set()
for i, num in enumerate(nums):
if i > k:
s.remove(nums[i - k - 1])
if num in s:
return True
s.add(num)
return False
只出现一次的数字(7.26)
思考:
看到这道题,第一反应想起来的是字典。
class Solution:
def singleNumber(self, nums: List[int]) -> int:
dict = {}
for key in nums:
dict[key] = dict.get(key, 0) + 1
for key in nums:
if dict[key] == 1:
return key
官方思路:
异或运算?!
任何数与0异或为任何数;
一个数与它本身进行异或运算等于 0
class Solution:
def singleNumber(self, nums: List[int]) -> int:
sum = 0
for i in nums:
sum^=i
return sum
多数元素(7.26)
自己用的方法:
class Solution:
def majorityElement(self, nums: List[int]) -> int:
n = len(nums)
dic = dict()
for key in nums:
dic[key] = dic.get(key,0) + 1
for key in nums:
if dic[key] > n/2:
return key
官方:(摩尔投票法)
class Solution:
def majorityElement(self, nums: List[int]) -> int:
count = 0
candidate = None
for num in nums:
if count == 0:
candidate = num
count += (1 if num == candidate else -1)
return candidate
汇总区间(7.27d)
class Solution {
public:
vector<string> summaryRanges(vector<int>& nums) {
vector<string> ret;
int i = 0;
int n = nums.size();
while (i < n) {
int low = i;
i++;
while (i < n && nums[i] == nums[i - 1] + 1) {
i++;
}
int high = i - 1;
string temp = to_string(nums[low]);
if (low < high) {
temp.append("->");
temp.append(to_string(nums[high]));
}
ret.push_back(move(temp));
}
return ret;
}
};
丢失的数字(7.28)
看到题目就想起来的做法:(但是执行用时久)
class Solution:
def missingNumber(self, nums: List[int]) -> int:
n = len(nums)
for i in range(n+1):
if i not in nums:
return i
官方方法一(排序):
class Solution:
def missingNumber(self, nums: List[int]) -> int:
n = len(nums)
nums.sort()
for i in range(n):
if nums[i] != i:
print(i)
return i
return n
官方方法二(位运算):
class Solution:
def missingNumber(self, nums: List[int]) -> int:
xor = 0
for i, num in enumerate(nums):
xor ^= i ^ num
return xor ^ len(nums)
移动零(7.29)
官方(双指针):
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
n = len(nums)
left = right = 0
while right < n:
if nums[right] != 0:
nums[left], nums[right] = nums[right], nums[left]
left += 1
right += 1
但是官方的答案我不是很懂,后面去看了B站一个up的讲解,说跟去重复项元素的思路是一样的,回过头一看,果然,差不多。
自己的代码:
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
n = len(nums)
fast = slow = 0
while fast < n:
if nums[fast] == 0:
fast += 1
else:
nums[slow] = nums[fast]
fast += 1
slow += 1
for i in range(slow,n):
nums[i] = 0
区域和检索 - 数组不可变(7.29)
class NumArray {
vector<int> sums;
public:
NumArray(vector<int>& nums) {
int n = nums.size();
sums.resize(n+1);
for(int i = 0; i < n; i++){
sums[i+1] = sums[i] + nums[i];
}
}
int sumRange(int i, int j) {
return sums[j+1] - sums[i];
}
};
/**
* Your NumArray object will be instantiated and called as such:
* NumArray* obj = new NumArray(nums);
* int param_1 = obj->sumRange(left,right);
*/
两个数组的交集(7.30)
代码(自己):
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
nums3 = []
for i in list(set(nums1)):
if i in nums2:
nums3.append(i)
return nums3
官方代码(两个集合):
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
set1 = set(nums1)
set2 = set(nums2)
return self.set_intersection(set1, set2)
def set_intersection(self, set1, set2):
if len(set1) > len(set2):
return self.set_intersection(set2, set1)
return [x for x in set1 if x in set2]
官方代码(排序+双指针):
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
nums1.sort()
nums2.sort()
length1, length2 = len(nums1), len(nums2)
intersection = list()
index1 = index2 = 0
while index1 < length1 and index2 < length2:
num1 = nums1[index1]
num2 = nums2[index2]
if num1 == num2:
# 保证加入元素的唯一性
if not intersection or num1 != intersection[-1]:
intersection.append(num1)
index1 += 1
index2 += 1
elif num1 < num2:
index1 += 1
else:
index2 += 1
return intersection
第三大的数(简单 8.8)
代码:
class Solution:
def thirdMax(self, nums: List[int]) -> int:
nums = list(set(nums))
n = len(nums)
if n < 3:
return max(nums)
nums.sort()
return nums[-3]
找到所有数组中消失的数字(8.8)
class Solution:
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
n = len(nums)
nums2 = [i for i in range(1,n+1)]
nums3 = set(nums2) - set(nums)
return list(nums3)
官方代码:
class Solution:
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
n = len(nums)
for num in nums:
x = (num - 1) % n
nums[x] += n
ret = [i + 1 for i, num in enumerate(nums) if num <= n]
return ret
分发饼干(8.16)
官方代码:
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g.sort()
s.sort()
n, m = len(g), len(s)
i = j = count = 0
while i < n and j < m:
while j < m and g[i] > s[j]:
j += 1
if j < m:
count += 1
i += 1
j += 1
return count
三数之和(8.16)
官方代码:
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
nums.sort()
ans = list()
# 枚举 a
for first in range(n):
# 需要和上一次枚举的数不相同
if first > 0 and nums[first] == nums[first - 1]:
continue
# c 对应的指针初始指向数组的最右端
third = n - 1
target = -nums[first]
# 枚举 b
for second in range(first + 1, n):
# 需要和上一次枚举的数不相同
if second > first + 1 and nums[second] == nums[second - 1]:
continue
# 需要保证 b 的指针在 c 的指针的左侧
while second < third and nums[second] + nums[third] > target:
third -= 1
# 如果指针重合,随着 b 后续的增加
# 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
if second == third:
break
if nums[second] + nums[third] == target:
ans.append([nums[first], nums[second], nums[third]])
return ans
最接近的三数之和(8.17)
代码:
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
n = len(nums)
best = 10**7
# 根据差值的绝对值来更新答案
def update(cur):
nonlocal best
if abs(cur - target) < abs(best - target):
best = cur
# 枚举 a
for i in range(n):
# 保证和上一次枚举的元素不相等
if i > 0 and nums[i] == nums[i - 1]:
continue
# 使用双指针枚举 b 和 c
j, k = i + 1, n - 1
while j < k:
s = nums[i] + nums[j] + nums[k]
# 如果和为 target 直接返回答案
if s == target:
return target
update(s)
if s > target:
# 如果和大于 target,移动 c 对应的指针
k0 = k - 1
# 移动到下一个不相等的元素
while j < k0 and nums[k0] == nums[k]:
k0 -= 1
k = k0
else:
# 如果和小于 target,移动 b 对应的指针
j0 = j + 1
# 移动到下一个不相等的元素
while j0 < k and nums[j0] == nums[j]:
j0 += 1
j = j0
return best
四数之和(8.19)