Merge branch 'master' of github.com:YDLIN/leetcode-master

This commit is contained in:
余杜林
2021-08-17 22:53:14 +08:00
15 changed files with 371 additions and 67 deletions

View File

@ -9,7 +9,7 @@
## 1. 两数之和
https://leetcode-cn.com/problems/two-sum/
[力扣题目链接](https://leetcode-cn.com/problems/two-sum/)
给定一个整数数组 nums 和一个目标值 target请你在该数组中找出和为目标值的那 两个 整数并返回他们的数组下标。
@ -29,10 +29,10 @@ https://leetcode-cn.com/problems/two-sum/
很明显暴力的解法是两层for循环查找时间复杂度是O(n^2)。
建议大家做这道题目之前,先做一下这两道
* [242. 有效的字母异位词](https://mp.weixin.qq.com/s/ffS8jaVFNUWyfn_8T31IdA)
* [349. 两个数组的交集](https://mp.weixin.qq.com/s/aMSA5zrp3jJcLjuSB0Es2Q)
* [242. 有效的字母异位词](https://www.programmercarl.com/0242.有效的字母异位词.html)
* [349. 两个数组的交集](https://www.programmercarl.com/0349.两个数组的交集.html)
[242. 有效的字母异位词](https://mp.weixin.qq.com/s/ffS8jaVFNUWyfn_8T31IdA) 这道题目是用数组作为哈希表来解决哈希问题,[349. 两个数组的交集](https://mp.weixin.qq.com/s/aMSA5zrp3jJcLjuSB0Es2Q)这道题目是通过set作为哈希表来解决哈希问题。
[242. 有效的字母异位词](https://www.programmercarl.com/0242.有效的字母异位词.html) 这道题目是用数组作为哈希表来解决哈希问题,[349. 两个数组的交集](https://www.programmercarl.com/0349.两个数组的交集.html)这道题目是通过set作为哈希表来解决哈希问题。
本题呢则要使用map那么来看一下使用数组和set来做哈希法的局限。
@ -51,7 +51,7 @@ C++中map有三种类型
std::unordered_map 底层实现为哈希表std::map 和std::multimap 的底层实现是红黑树。
同理std::map 和std::multimap 的key也是有序的这个问题也经常作为面试题考察对语言容器底层的理解。 更多哈希表的理论知识请看[关于哈希表,你该了解这些!](https://mp.weixin.qq.com/s/RSUANESA_tkhKhYe3ZR8Jg)。
同理std::map 和std::multimap 的key也是有序的这个问题也经常作为面试题考察对语言容器底层的理解。 更多哈希表的理论知识请看[关于哈希表,你该了解这些!](https://www.programmercarl.com/哈希表理论基础.html)。
**这道题目中并不需要key有序选择std::unordered_map 效率更高!**
@ -110,13 +110,14 @@ Python
```python
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashmap={}
for ind,num in enumerate(nums):
hashmap[num] = ind
for i,num in enumerate(nums):
j = hashmap.get(target - num)
if j is not None and i!=j:
return [i,j]
records = dict()
# 用枚举更方便,就不需要通过索引再去取当前位置的值
for idx, val in enumerate(nums):
if target - val not in records:
records[val] = idx
else:
return [records[target - val], idx] # 如果存在就返回字典记录索引和当前索引
```

View File

@ -388,6 +388,44 @@ class Solution:
res += res1
return res
```
动态规划
```python3
class Solution:
def trap(self, height: List[int]) -> int:
leftheight, rightheight = [0]*len(height), [0]*len(height)
leftheight[0]=height[0]
for i in range(1,len(height)):
leftheight[i]=max(leftheight[i-1],height[i])
rightheight[-1]=height[-1]
for i in range(len(height)-2,-1,-1):
rightheight[i]=max(rightheight[i+1],height[i])
result = 0
for i in range(0,len(height)):
summ = min(leftheight[i],rightheight[i])-height[i]
result += summ
return result
```
单调栈
```python3
class Solution:
def trap(self, height: List[int]) -> int:
st =[0]
result = 0
for i in range(1,len(height)):
while st!=[] and height[i]>height[st[-1]]:
midh = height[st[-1]]
st.pop()
if st!=[]:
hright = height[i]
hleft = height[st[-1]]
h = min(hright,hleft)-midh
w = i-st[-1]-1
result+=h*w
st.append(i)
return result
```
Go:

View File

@ -91,18 +91,18 @@ if (word1[i - 1] != word2[j - 1])
`if (word1[i - 1] != word2[j - 1])`,此时就需要编辑了,如何编辑呢?
* 操作一word1增加一个元素,使其word1[i - 1]与word2[j - 1]相同,那么就是以下标i-2为结尾的word1 与 j-1为结尾的word2的最近编辑距离 加上一个增加元素的操作。
* 操作一word1删除一个元素那么就是以下标i - 2为结尾的word1 与 j-1为结尾的word2的最近编辑距离 加上一个操作。
`dp[i][j] = dp[i - 1][j] + 1;`
* 操作二word2添加一个元素,使其word1[i - 1]与word2[j - 1]相同,那么就是以下标i-1为结尾的word1 与 j-2为结尾的word2的最近编辑距离 加上一个增加元素的操作。
* 操作二word2删除一个元素那么就是以下标i - 1为结尾的word1 与 j-2为结尾的word2的最近编辑距离 加上一个操作。
`dp[i][j] = dp[i][j - 1] + 1;`
这里有同学发现了,怎么都是添加元素,删除元素去哪了。
这里有同学发现了,怎么都是删除元素,添加元素去哪了。
**word2添加一个元素相当于word1删除一个元素**,例如 `word1 = "ad" word2 = "a"``word1`删除元素`'d'``word2`添加一个元素`'d'`,变成`word1="a", word2="ad"` 最终的操作数是一样! dp数组如下图所示意的
**word2添加一个元素相当于word1删除一个元素**,例如 `word1 = "ad" word2 = "a"``word1`删除元素`'d'``word2`添加一个元素`'d'`,变成`word1="a", word2="ad"` 最终的操作数是一样! dp数组如下图所示意的
```
a a d

View File

@ -191,4 +191,57 @@ public:
这里我依然建议大家按部就班把版本一写出来,把情况一二三分析清楚,然后在精简代码到版本二。 直接看版本二容易忽略细节!
## 其他语言版本
Java:
Python:
动态规划
```python3
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
result = 0
minleftindex, minrightindex = [0]*len(heights), [0]*len(heights)
minleftindex[0]=-1
for i in range(1,len(heights)):
t = i-1
while t>=0 and heights[t]>=heights[i]: t=minleftindex[t]
minleftindex[i]=t
minrightindex[-1]=len(heights)
for i in range(len(heights)-2,-1,-1):
t=i+1
while t<len(heights) and heights[t]>=heights[i]: t=minrightindex[t]
minrightindex[i]=t
for i in range(0,len(heights)):
left = minleftindex[i]
right = minrightindex[i]
summ = (right-left-1)*heights[i]
result = max(result,summ)
return result
```
单调栈 版本二
```python3
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
heights.insert(0,0) # 数组头部加入元素0
heights.append(0) # 数组尾部加入元素0
st = [0]
result = 0
for i in range(1,len(heights)):
while st!=[] and heights[i]<heights[st[-1]]:
midh = heights[st[-1]]
st.pop()
if st!=[]:
minrightindex = i
minleftindex = st[-1]
summ = (minrightindex-minleftindex-1)*midh
result = max(summ,result)
st.append(i)
return result
```
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>

View File

@ -1205,6 +1205,35 @@ public:
};
```
java代码
```java
class Solution {
public Node connect(Node root) {
Queue<Node> tmpQueue = new LinkedList<Node>();
if (root != null) tmpQueue.add(root);
while (tmpQueue.size() != 0){
int size = tmpQueue.size();
Node cur = tmpQueue.poll();
if (cur.left != null) tmpQueue.add(cur.left);
if (cur.right != null) tmpQueue.add(cur.right);
for (int index = 1; index < size; index++){
Node next = tmpQueue.poll();
if (next.left != null) tmpQueue.add(next.left);
if (next.right != null) tmpQueue.add(next.right);
cur.next = next;
cur = next;
}
}
return root;
}
}
```
python代码

View File

@ -165,7 +165,32 @@ public:
Java
Python
```python3
class Solution:
def sumNumbers(self, root: TreeNode) -> int:
res = 0
path = []
def backtrace(root):
nonlocal res
if not root: return # 节点空则返回
path.append(root.val)
if not root.left and not root.right: # 遇到了叶子节点
res += get_sum(path)
if root.left: # 左子树不空
backtrace(root.left)
if root.right: # 右子树不空
backtrace(root.right)
path.pop()
def get_sum(arr):
s = 0
for i in range(len(arr)):
s = s * 10 + arr[i]
return s
backtrace(root)
return res
```
Go
JavaScript

View File

@ -222,7 +222,61 @@ public class ReorderList {
```
Python
```python3
# 方法二 双向队列
class Solution:
def reorderList(self, head: ListNode) -> None:
"""
Do not return anything, modify head in-place instead.
"""
d = collections.deque()
tmp = head
while tmp.next: # 链表除了首元素全部加入双向队列
d.append(tmp.next)
tmp = tmp.next
tmp = head
while len(d): # 一后一前加入链表
tmp.next = d.pop()
tmp = tmp.next
if len(d):
tmp.next = d.popleft()
tmp = tmp.next
tmp.next = None # 尾部置空
# 方法三 反转链表
class Solution:
def reorderList(self, head: ListNode) -> None:
if head == None or head.next == None:
return True
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
right = slow.next # 分割右半边
slow.next = None # 切断
right = self.reverseList(right) #反转右半边
left = head
# 左半边一定比右半边长, 因此判断右半边即可
while right:
curLeft = left.next
left.next = right
left = curLeft
curRight = right.next
right.next = left
right = curRight
def reverseList(self, head: ListNode) -> ListNode:
cur = head
pre = None
while(cur!=None):
temp = cur.next # 保存一下cur的下一个节点
cur.next = pre # 反转
pre = cur
cur = temp
return pre
```
Go
JavaScript

View File

@ -111,25 +111,29 @@ Python
```python
class Solution:
def isHappy(self, n: int) -> bool:
set_ = set()
while 1:
sum_ = self.getSum(n)
if sum_ == 1:
def calculate_happy(num):
sum_ = 0
# 从个位开始依次取,平方求和
while num:
sum_ += (num % 10) ** 2
num = num // 10
return sum_
# 记录中间结果
record = set()
while True:
n = calculate_happy(n)
if n == 1:
return True
#如果这个sum曾经出现过说明已经陷入了无限循环了立刻return false
if sum_ in set_:
# 如果中间结果重复出现,说明陷入死循环了,该数不是快乐数
if n in record:
return False
else:
set_.add(sum_)
n = sum_
#取数值各个位上的单数之和
def getSum(self, n):
sum_ = 0
while n > 0:
sum_ += (n%10) * (n%10)
n //= 10
return sum_
record.add(n)
```
Go

View File

@ -148,7 +148,62 @@ public:
## Python
```python
```python3
#数组模拟
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
length = 0
tmp = head
while tmp: #求链表长度
length += 1
tmp = tmp.next
result = [0] * length
tmp = head
index = 0
while tmp: #链表元素加入数组
result[index] = tmp.val
index += 1
tmp = tmp.next
i, j = 0, length - 1
while i < j: # 判断回文
if result[i] != result[j]:
return False
i += 1
j -= 1
return True
#反转后半部分链表
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
if head == None or head.next == None:
return True
slow, fast = head, head
while fast and fast.next:
pre = slow
slow = slow.next
fast = fast.next.next
pre.next = None # 分割链表
cur1 = head # 前半部分
cur2 = self.reverseList(slow) # 反转后半部分总链表长度如果是奇数cur2比cur1多一个节点
while cur1:
if cur1.val != cur2.val:
return False
cur1 = cur1.next
cur2 = cur2.next
return True
def reverseList(self, head: ListNode) -> ListNode:
cur = head
pre = None
while(cur!=None):
temp = cur.next # 保存一下cur的下一个节点
cur.next = pre # 反转
pre = cur
cur = temp
return pre
```
## Go

View File

@ -121,13 +121,7 @@ Python
```python
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
result_set = set()
set1 = set(nums1)
for num in nums2:
if num in set1:
result_set.add(num) # set1里出现的nums2元素 存放到结果
return list(result_set)
return list(set(nums1) & set(nums2)) # 两个数组先变成集合,求交集后还原为数组
```

View File

@ -89,7 +89,16 @@ class Solution {
## Python
```python
```python3
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
numSum = sum(nums) #数组总和
leftSum = 0
for i in range(len(nums)):
if numSum - leftSum -nums[i] == leftSum: #左右和相等
return i
leftSum += nums[i]
return -1
```
## Go

View File

@ -149,7 +149,32 @@ class Solution {
## Python
```python
```python3
#方法2
class Solution:
def sortArrayByParityII(self, nums: List[int]) -> List[int]:
result = [0]*len(nums)
evenIndex = 0
oddIndex = 1
for i in range(len(nums)):
if nums[i] % 2: #奇数
result[oddIndex] = nums[i]
oddIndex += 2
else: #偶数
result[evenIndex] = nums[i]
evenIndex += 2
return result
#方法3
class Solution:
def sortArrayByParityII(self, nums: List[int]) -> List[int]:
oddIndex = 1
for i in range(0,len(nums),2): #步长为2
if nums[i] % 2: #偶数位遇到奇数
while nums[oddIndex] % 2: #奇数位找偶数
oddIndex += 2
nums[i], nums[oddIndex] = nums[oddIndex], nums[i]
return nums
```
## Go

View File

@ -252,6 +252,24 @@ func sortedSquares(_ nums: [Int]) -> [Int] {
}
```
Ruby:
```ruby
def sorted_squares(nums)
left, right, result = 0, nums.size - 1, []
while left <= right
if nums[left]**2 > nums[right]**2
result << nums[left]**2
left += 1
else
result << nums[right]**2
right -= 1
end
end
result.reverse
end
```
-----------------------

View File

@ -141,6 +141,18 @@ class Solution:
# 空间复杂度O(n)python的string为不可变需要开辟同样大小的list空间来修改
```
```python 3
#方法三:考虑不能用切片的情况下,利用模+下标实现
class Solution:
def reverseLeftWords(self, s: str, n: int) -> str:
new_s = ''
for i in range(len(s)):
j = (i+n)%len(s)
new_s = new_s + s[j]
return new_s
```
Go
```go

View File

@ -160,34 +160,21 @@ Python
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
lengthA,lengthB = 0,0
curA,curB = headA,headB
while(curA!=None): #求链表A的长度
curA = curA.next
lengthA +=1
while(curB!=None): #求链表B的长度
curB = curB.next
lengthB +=1
curA, curB = headA, headB
"""
根据快慢法则,走的快的一定会追上走得慢的。
在这道题里,有的链表短,他走完了就去走另一条链表,我们可以理解为走的快的指针。
if lengthB>lengthA: #让curA为最长链表的头lenA为其长度
lengthA, lengthB = lengthB, lengthA
curA, curB = curB, curA
那么,只要其中一个链表走完了,就去走另一条链表的路。如果有交点,他们最终一定会在同一个
位置相遇
"""
cur_a, cur_b = headA, headB # 用两个指针代替a和b
gap = lengthA - lengthB #求长度差
while(gap!=0):
curA = curA.next #让curA和curB在同一起点上
gap -= 1
while(curA!=None):
if curA == curB:
return curA
else:
curA = curA.next
curB = curB.next
return None
while cur_a != cur_b:
cur_a = cur_a.next if cur_a else headB # 如果a走完了那么就切换到b走
cur_b = cur_b.next if cur_b else headA # 同理b走完了就切换到a
return cur_a
```
Go