mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-09 19:44:45 +08:00
Merge remote-tracking branch 'origin/master' into fix_0494_bug
This commit is contained in:
@ -162,18 +162,44 @@ class Solution {
|
|||||||
|
|
||||||
Python:
|
Python:
|
||||||
```python3
|
```python3
|
||||||
|
# 方法一,仅使用栈,更省空间
|
||||||
class Solution:
|
class Solution:
|
||||||
def isValid(self, s: str) -> bool:
|
def isValid(self, s: str) -> bool:
|
||||||
stack = [] # 保存还未匹配的左括号
|
stack = []
|
||||||
mapping = {")": "(", "]": "[", "}": "{"}
|
|
||||||
for i in s:
|
for item in s:
|
||||||
if i in "([{": # 当前是左括号,则入栈
|
if item == '(':
|
||||||
stack.append(i)
|
stack.append(')')
|
||||||
elif stack and stack[-1] == mapping[i]: # 当前是配对的右括号则出栈
|
elif item == '[':
|
||||||
stack.pop()
|
stack.append(']')
|
||||||
else: # 不是匹配的右括号或者没有左括号与之匹配,则返回false
|
elif item == '{':
|
||||||
|
stack.append('}')
|
||||||
|
elif not stack or stack[-1] != item:
|
||||||
return False
|
return False
|
||||||
return stack == [] # 最后必须正好把左括号匹配完
|
else:
|
||||||
|
stack.pop()
|
||||||
|
|
||||||
|
return True if not stack else False
|
||||||
|
```
|
||||||
|
|
||||||
|
```python3
|
||||||
|
# 方法二,使用字典
|
||||||
|
class Solution:
|
||||||
|
def isValid(self, s: str) -> bool:
|
||||||
|
stack = []
|
||||||
|
mapping = {
|
||||||
|
'(': ')',
|
||||||
|
'[': ']',
|
||||||
|
'{': '}'
|
||||||
|
}
|
||||||
|
for item in s:
|
||||||
|
if item in mapping.keys():
|
||||||
|
stack.append(mapping[item])
|
||||||
|
elif not stack or stack[-1] != item:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
stack.pop()
|
||||||
|
return True if not stack else False
|
||||||
```
|
```
|
||||||
|
|
||||||
Go:
|
Go:
|
||||||
|
@ -160,21 +160,29 @@ class Solution {
|
|||||||
|
|
||||||
Python:
|
Python:
|
||||||
```python
|
```python
|
||||||
|
# Definition for singly-linked list.
|
||||||
|
# class ListNode:
|
||||||
|
# def __init__(self, val=0, next=None):
|
||||||
|
# self.val = val
|
||||||
|
# self.next = next
|
||||||
|
|
||||||
class Solution:
|
class Solution:
|
||||||
def swapPairs(self, head: ListNode) -> ListNode:
|
def swapPairs(self, head: ListNode) -> ListNode:
|
||||||
dummy = ListNode(0) #设置一个虚拟头结点
|
res = ListNode(next=head)
|
||||||
dummy.next = head
|
pre = res
|
||||||
cur = dummy
|
|
||||||
while cur.next and cur.next.next:
|
|
||||||
tmp = cur.next #记录临时节点
|
|
||||||
tmp1 = cur.next.next.next #记录临时节点
|
|
||||||
|
|
||||||
cur.next = cur.next.next #步骤一
|
# 必须有pre的下一个和下下个才能交换,否则说明已经交换结束了
|
||||||
cur.next.next = tmp #步骤二
|
while pre.next and pre.next.next:
|
||||||
cur.next.next.next = tmp1 #步骤三
|
cur = pre.next
|
||||||
|
post = pre.next.next
|
||||||
|
|
||||||
cur = cur.next.next #cur移动两位,准备下一轮交换
|
# pre,cur,post对应最左,中间的,最右边的节点
|
||||||
return dummy.next
|
cur.next = post.next
|
||||||
|
post.next = cur
|
||||||
|
pre.next = post
|
||||||
|
|
||||||
|
pre = pre.next.next
|
||||||
|
return res.next
|
||||||
```
|
```
|
||||||
|
|
||||||
Go:
|
Go:
|
||||||
|
@ -366,6 +366,58 @@ public:
|
|||||||
|
|
||||||
Java:
|
Java:
|
||||||
|
|
||||||
|
双指针法
|
||||||
|
```java
|
||||||
|
class Solution {
|
||||||
|
public int trap(int[] height) {
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i < height.length; i++) {
|
||||||
|
// 第一个柱子和最后一个柱子不接雨水
|
||||||
|
if (i==0 || i== height.length - 1) continue;
|
||||||
|
|
||||||
|
int rHeight = height[i]; // 记录右边柱子的最高高度
|
||||||
|
int lHeight = height[i]; // 记录左边柱子的最高高度
|
||||||
|
for (int r = i+1; r < height.length; r++) {
|
||||||
|
if (height[r] > rHeight) rHeight = height[r];
|
||||||
|
}
|
||||||
|
for (int l = i-1; l >= 0; l--) {
|
||||||
|
if(height[l] > lHeight) lHeight = height[l];
|
||||||
|
}
|
||||||
|
int h = Math.min(lHeight, rHeight) - height[i];
|
||||||
|
if (h > 0) sum += h;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
动态规划法
|
||||||
|
```java
|
||||||
|
class Solution {
|
||||||
|
public int trap(int[] height) {
|
||||||
|
int length = height.length;
|
||||||
|
if (length <= 2) return 0;
|
||||||
|
int[] maxLeft = new int[length];
|
||||||
|
int[] maxRight = new int[length];
|
||||||
|
|
||||||
|
// 记录每个柱子左边柱子最大高度
|
||||||
|
maxLeft[0] = height[0];
|
||||||
|
for (int i = 1; i< length; i++) maxLeft[i] = Math.max(height[i], maxLeft[i-1]);
|
||||||
|
|
||||||
|
// 记录每个柱子右边柱子最大高度
|
||||||
|
maxRight[length - 1] = height[length - 1];
|
||||||
|
for(int i = length - 2; i >= 0; i--) maxRight[i] = Math.max(height[i], maxRight[i+1]);
|
||||||
|
|
||||||
|
// 求和
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
int count = Math.min(maxLeft[i], maxRight[i]) - height[i];
|
||||||
|
if (count > 0) sum += count;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
Python:
|
Python:
|
||||||
|
|
||||||
双指针法
|
双指针法
|
||||||
|
@ -195,6 +195,40 @@ public:
|
|||||||
|
|
||||||
Java:
|
Java:
|
||||||
|
|
||||||
|
动态规划
|
||||||
|
```java
|
||||||
|
class Solution {
|
||||||
|
public int largestRectangleArea(int[] heights) {
|
||||||
|
int length = heights.length;
|
||||||
|
int[] minLeftIndex = new int [length];
|
||||||
|
int[] maxRigthIndex = new int [length];
|
||||||
|
|
||||||
|
// 记录左边第一个小于该柱子的下标
|
||||||
|
minLeftIndex[0] = -1 ;
|
||||||
|
for (int i = 1; i < length; i++) {
|
||||||
|
int t = i - 1;
|
||||||
|
// 这里不是用if,而是不断向右寻找的过程
|
||||||
|
while (t >= 0 && heights[t] >= heights[i]) t = minLeftIndex[t];
|
||||||
|
minLeftIndex[i] = t;
|
||||||
|
}
|
||||||
|
// 记录每个柱子 右边第一个小于该柱子的下标
|
||||||
|
maxRigthIndex[length - 1] = length;
|
||||||
|
for (int i = length - 2; i >= 0; i--) {
|
||||||
|
int t = i + 1;
|
||||||
|
while(t < length && heights[t] >= heights[i]) t = maxRigthIndex[t];
|
||||||
|
maxRigthIndex[i] = t;
|
||||||
|
}
|
||||||
|
// 求和
|
||||||
|
int result = 0;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
int sum = heights[i] * (maxRigthIndex[i] - minLeftIndex[i] - 1);
|
||||||
|
result = Math.max(sum, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Python:
|
Python:
|
||||||
|
|
||||||
动态规划
|
动态规划
|
||||||
|
@ -1129,7 +1129,7 @@ var largestValues = function(root) {
|
|||||||
queue.push(root);
|
queue.push(root);
|
||||||
while(root!==null&&queue.length){
|
while(root!==null&&queue.length){
|
||||||
//设置max初始值就是队列的第一个元素
|
//设置max初始值就是队列的第一个元素
|
||||||
let max=queue[0];
|
let max=queue[0].val;
|
||||||
let length=queue.length;
|
let length=queue.length;
|
||||||
while(length--){
|
while(length--){
|
||||||
let node = queue.shift();
|
let node = queue.shift();
|
||||||
@ -1532,6 +1532,29 @@ Java:
|
|||||||
|
|
||||||
|
|
||||||
Python:
|
Python:
|
||||||
|
```python 3
|
||||||
|
class Solution:
|
||||||
|
def maxDepth(self, root: TreeNode) -> int:
|
||||||
|
if root == None:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
queue_ = [root]
|
||||||
|
result = []
|
||||||
|
while queue_:
|
||||||
|
length = len(queue_)
|
||||||
|
sub = []
|
||||||
|
for i in range(length):
|
||||||
|
cur = queue_.pop(0)
|
||||||
|
sub.append(cur.val)
|
||||||
|
#子节点入队列
|
||||||
|
if cur.left: queue_.append(cur.left)
|
||||||
|
if cur.right: queue_.append(cur.right)
|
||||||
|
result.append(sub)
|
||||||
|
|
||||||
|
|
||||||
|
return len(result)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Go:
|
Go:
|
||||||
|
|
||||||
@ -1539,6 +1562,8 @@ JavaScript:
|
|||||||
|
|
||||||
# 111.二叉树的最小深度
|
# 111.二叉树的最小深度
|
||||||
|
|
||||||
|
题目地址:https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/
|
||||||
|
|
||||||
相对于 104.二叉树的最大深度 ,本题还也可以使用层序遍历的方式来解决,思路是一样的。
|
相对于 104.二叉树的最大深度 ,本题还也可以使用层序遍历的方式来解决,思路是一样的。
|
||||||
|
|
||||||
**需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点**
|
**需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点**
|
||||||
@ -1574,7 +1599,35 @@ public:
|
|||||||
Java:
|
Java:
|
||||||
|
|
||||||
|
|
||||||
Python:
|
Python 3:
|
||||||
|
|
||||||
|
```python 3
|
||||||
|
# Definition for a binary tree node.
|
||||||
|
# class TreeNode:
|
||||||
|
# def __init__(self, val=0, left=None, right=None):
|
||||||
|
# self.val = val
|
||||||
|
# self.left = left
|
||||||
|
# self.right = right
|
||||||
|
class Solution:
|
||||||
|
def minDepth(self, root: TreeNode) -> int:
|
||||||
|
if root == None:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
#根节点的深度为1
|
||||||
|
queue_ = [(root,1)]
|
||||||
|
while queue_:
|
||||||
|
cur, depth = queue_.pop(0)
|
||||||
|
|
||||||
|
if cur.left == None and cur.right == None:
|
||||||
|
return depth
|
||||||
|
#先左子节点,由于左子节点没有孩子,则就是这一层了
|
||||||
|
if cur.left:
|
||||||
|
queue_.append((cur.left,depth + 1))
|
||||||
|
if cur.right:
|
||||||
|
queue_.append((cur.right,depth + 1))
|
||||||
|
|
||||||
|
return 0
|
||||||
|
```
|
||||||
|
|
||||||
Go:
|
Go:
|
||||||
|
|
||||||
|
@ -223,17 +223,19 @@ var evalRPN = function(tokens) {
|
|||||||
python3
|
python3
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def evalRPN(tokens) -> int:
|
class Solution:
|
||||||
stack = list()
|
def evalRPN(self, tokens: List[str]) -> int:
|
||||||
for i in range(len(tokens)):
|
stack = []
|
||||||
if tokens[i] not in ["+", "-", "*", "/"]:
|
for item in tokens:
|
||||||
stack.append(tokens[i])
|
if item not in {"+", "-", "*", "/"}:
|
||||||
else:
|
stack.append(item)
|
||||||
tmp1 = stack.pop()
|
else:
|
||||||
tmp2 = stack.pop()
|
first_num, second_num = stack.pop(), stack.pop()
|
||||||
res = eval(tmp2+tokens[i]+tmp1)
|
stack.append(
|
||||||
stack.append(str(int(res)))
|
int(eval(f'{second_num} {item} {first_num}')) # 第一个出来的在运算符后面
|
||||||
return stack[-1]
|
)
|
||||||
|
return int(stack.pop()) # 如果一开始只有一个数,那么会是字符串形式的
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ class Solution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 版本二: 空间优化
|
// 版本二: 二维 dp数组
|
||||||
class Solution {
|
class Solution {
|
||||||
public int maxProfit(int k, int[] prices) {
|
public int maxProfit(int k, int[] prices) {
|
||||||
if (prices.length == 0) return 0;
|
if (prices.length == 0) return 0;
|
||||||
@ -220,6 +220,25 @@ class Solution {
|
|||||||
return dp[len - 1][k*2];
|
return dp[len - 1][k*2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//版本三:一维 dp数组
|
||||||
|
class Solution {
|
||||||
|
public int maxProfit(int k, int[] prices) {
|
||||||
|
//在版本二的基础上,由于我们只关心前一天的股票买入情况,所以只存储前一天的股票买入情况
|
||||||
|
if(prices.length==0)return 0;
|
||||||
|
int[] dp=new int[2*k+1];
|
||||||
|
for (int i = 1; i <2*k ; i+=2) {
|
||||||
|
dp[i]=-prices[0];
|
||||||
|
}
|
||||||
|
for (int i = 0; i <prices.length ; i++) {
|
||||||
|
for (int j = 1; j <2*k ; j+=2) {
|
||||||
|
dp[j]=Math.max(dp[j],dp[j-1]-prices[i]);
|
||||||
|
dp[j+1]=Math.max(dp[j+1],dp[j]+prices[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[2*k];
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -245,13 +245,15 @@ Python:
|
|||||||
# def __init__(self, val=0, next=None):
|
# def __init__(self, val=0, next=None):
|
||||||
# self.val = val
|
# self.val = val
|
||||||
# self.next = next
|
# self.next = next
|
||||||
|
|
||||||
class Solution:
|
class Solution:
|
||||||
def removeElements(self, head: ListNode, val: int) -> ListNode:
|
def removeElements(self, head: ListNode, val: int) -> ListNode:
|
||||||
dummy_head = ListNode(next=head) #添加一个虚拟节点
|
dummy_head = ListNode(next=head)
|
||||||
cur = dummy_head
|
cur = dummy_head
|
||||||
while(cur.next!=None):
|
|
||||||
if(cur.next.val == val):
|
while cur.next:
|
||||||
cur.next = cur.next.next #删除cur.next节点
|
if cur.next.val == val:
|
||||||
|
cur.next = cur.next.next # 删除下一个节点
|
||||||
else:
|
else:
|
||||||
cur = cur.next
|
cur = cur.next
|
||||||
return dummy_head.next
|
return dummy_head.next
|
||||||
@ -304,8 +306,7 @@ var removeElements = function(head, val) {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Swift:
|
Swift:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
/**
|
/**
|
||||||
* Definition for singly-linked list.
|
* Definition for singly-linked list.
|
||||||
|
@ -334,6 +334,43 @@ fun reverseList(head: ListNode?): ListNode? {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Swift:
|
||||||
|
```swift
|
||||||
|
/// 双指针法 (迭代)
|
||||||
|
/// - Parameter head: 头结点
|
||||||
|
/// - Returns: 翻转后的链表头结点
|
||||||
|
func reverseList(_ head: ListNode?) -> ListNode? {
|
||||||
|
if head == nil || head?.next == nil {
|
||||||
|
return head
|
||||||
|
}
|
||||||
|
var pre: ListNode? = nil
|
||||||
|
var cur: ListNode? = head
|
||||||
|
var temp: ListNode? = nil
|
||||||
|
while cur != nil {
|
||||||
|
temp = cur?.next
|
||||||
|
cur?.next = pre
|
||||||
|
pre = cur
|
||||||
|
cur = temp
|
||||||
|
}
|
||||||
|
return pre
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 递归
|
||||||
|
/// - Parameter head: 头结点
|
||||||
|
/// - Returns: 翻转后的链表头结点
|
||||||
|
func reverseList2(_ head: ListNode?) -> ListNode? {
|
||||||
|
return reverse(pre: nil, cur: head)
|
||||||
|
}
|
||||||
|
func reverse(pre: ListNode?, cur: ListNode?) -> ListNode? {
|
||||||
|
if cur == nil {
|
||||||
|
return pre
|
||||||
|
}
|
||||||
|
let temp: ListNode? = cur?.next
|
||||||
|
cur?.next = pre
|
||||||
|
return reverse(pre: cur, cur: temp)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||||
|
@ -294,53 +294,66 @@ Python:
|
|||||||
|
|
||||||
```python
|
```python
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
class MyStack:
|
class MyStack:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""
|
"""
|
||||||
Initialize your data structure here.
|
Python普通的Queue或SimpleQueue没有类似于peek的功能
|
||||||
|
也无法用索引访问,在实现top的时候较为困难。
|
||||||
|
|
||||||
|
用list可以,但是在使用pop(0)的时候时间复杂度为O(n)
|
||||||
|
因此这里使用双向队列,我们保证只执行popleft()和append(),因为deque可以用索引访问,可以实现和peek相似的功能
|
||||||
|
|
||||||
|
in - 存所有数据
|
||||||
|
out - 仅在pop的时候会用到
|
||||||
"""
|
"""
|
||||||
#使用两个队列来实现
|
self.queue_in = deque()
|
||||||
self.que1 = deque()
|
self.queue_out = deque()
|
||||||
self.que2 = deque()
|
|
||||||
|
|
||||||
def push(self, x: int) -> None:
|
def push(self, x: int) -> None:
|
||||||
"""
|
"""
|
||||||
Push element x onto stack.
|
直接append即可
|
||||||
"""
|
"""
|
||||||
self.que1.append(x)
|
self.queue_in.append(x)
|
||||||
|
|
||||||
|
|
||||||
def pop(self) -> int:
|
def pop(self) -> int:
|
||||||
"""
|
"""
|
||||||
Removes the element on top of the stack and returns that element.
|
1. 首先确认不空
|
||||||
|
2. 因为队列的特殊性,FIFO,所以我们只有在pop()的时候才会使用queue_out
|
||||||
|
3. 先把queue_in中的所有元素(除了最后一个),依次出列放进queue_out
|
||||||
|
4. 交换in和out,此时out里只有一个元素
|
||||||
|
5. 把out中的pop出来,即是原队列的最后一个
|
||||||
|
|
||||||
|
tip:这不能像栈实现队列一样,因为另一个queue也是FIFO,如果执行pop()它不能像
|
||||||
|
stack一样从另一个pop(),所以干脆in只用来存数据,pop()的时候两个进行交换
|
||||||
"""
|
"""
|
||||||
size = len(self.que1)
|
if self.empty():
|
||||||
size -= 1#这里先减一是为了保证最后面的元素
|
return None
|
||||||
while size > 0:
|
|
||||||
size -= 1
|
|
||||||
self.que2.append(self.que1.popleft())
|
|
||||||
|
|
||||||
|
for i in range(len(self.queue_in) - 1):
|
||||||
|
self.queue_out.append(self.queue_in.popleft())
|
||||||
|
|
||||||
result = self.que1.popleft()
|
self.queue_in, self.queue_out = self.queue_out, self.queue_in # 交换in和out,这也是为啥in只用来存
|
||||||
self.que1, self.que2= self.que2, self.que1#将que2和que1交换 que1经过之前的操作应该是空了
|
return self.queue_out.popleft()
|
||||||
#一定注意不能直接使用que1 = que2 这样que2的改变会影响que1 可以用浅拷贝
|
|
||||||
return result
|
|
||||||
|
|
||||||
def top(self) -> int:
|
def top(self) -> int:
|
||||||
"""
|
"""
|
||||||
Get the top element.
|
1. 首先确认不空
|
||||||
|
2. 我们仅有in会存放数据,所以返回第一个即可
|
||||||
"""
|
"""
|
||||||
return self.que1[-1]
|
if self.empty():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.queue_in[-1]
|
||||||
|
|
||||||
|
|
||||||
def empty(self) -> bool:
|
def empty(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Returns whether the stack is empty.
|
因为只有in存了数据,只要判断in是不是有数即可
|
||||||
"""
|
"""
|
||||||
#print(self.que1)
|
return len(self.queue_in) == 0
|
||||||
if len(self.que1) == 0:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -281,48 +281,60 @@ class MyQueue {
|
|||||||
|
|
||||||
Python:
|
Python:
|
||||||
```python
|
```python
|
||||||
# 使用两个栈实现先进先出的队列
|
|
||||||
class MyQueue:
|
class MyQueue:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""
|
"""
|
||||||
Initialize your data structure here.
|
in主要负责push,out主要负责pop
|
||||||
"""
|
"""
|
||||||
self.stack1 = list()
|
self.stack_in = []
|
||||||
self.stack2 = list()
|
self.stack_out = []
|
||||||
|
|
||||||
|
|
||||||
def push(self, x: int) -> None:
|
def push(self, x: int) -> None:
|
||||||
"""
|
"""
|
||||||
Push element x to the back of queue.
|
有新元素进来,就往in里面push
|
||||||
"""
|
"""
|
||||||
# self.stack1用于接受元素
|
self.stack_in.append(x)
|
||||||
self.stack1.append(x)
|
|
||||||
|
|
||||||
def pop(self) -> int:
|
def pop(self) -> int:
|
||||||
"""
|
"""
|
||||||
Removes the element from in front of queue and returns that element.
|
1. 检查如果out里面元素,则直接pop
|
||||||
|
2. 如果out没有元素,就把in里面的元素(除了第一个)依次pop后装进out里面
|
||||||
|
3. 直接把in剩下的元素pop出来,就是queue头部的
|
||||||
"""
|
"""
|
||||||
# self.stack2用于弹出元素,如果self.stack2为[],则将self.stack1中元素全部弹出给self.stack2
|
if self.empty:
|
||||||
if self.stack2 == []:
|
return None
|
||||||
while self.stack1:
|
|
||||||
tmp = self.stack1.pop()
|
if self.stack_out:
|
||||||
self.stack2.append(tmp)
|
return self.stack_out.pop()
|
||||||
return self.stack2.pop()
|
else:
|
||||||
|
for i in range(1, len(self.stack_in)):
|
||||||
|
self.stack_out.append(self.stack_in.pop())
|
||||||
|
return self.stack_in.pop()
|
||||||
|
|
||||||
|
|
||||||
def peek(self) -> int:
|
def peek(self) -> int:
|
||||||
"""
|
"""
|
||||||
Get the front element.
|
1. 查out有没有元素,有就把最上面的返回
|
||||||
|
2. 如果out没有元素,就把in最下面的返回
|
||||||
"""
|
"""
|
||||||
if self.stack2 == []:
|
if self.empty:
|
||||||
while self.stack1:
|
return None
|
||||||
tmp = self.stack1.pop()
|
|
||||||
self.stack2.append(tmp)
|
if self.stack_out:
|
||||||
return self.stack2[-1]
|
return self.stack_out[-1]
|
||||||
|
else:
|
||||||
|
return self.stack_in[0]
|
||||||
|
|
||||||
|
|
||||||
def empty(self) -> bool:
|
def empty(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Returns whether the queue is empty.
|
只要in或者out有元素,说明队列不为空
|
||||||
"""
|
"""
|
||||||
return self.stack1 == [] and self.stack2 == []
|
return not (self.stack_in or self.stack_out)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -161,6 +161,7 @@ public:
|
|||||||
Java:
|
Java:
|
||||||
```Java
|
```Java
|
||||||
class Solution {
|
class Solution {
|
||||||
|
// 版本一,先遍历物品, 再遍历背包
|
||||||
public int numSquares(int n) {
|
public int numSquares(int n) {
|
||||||
int max = Integer.MAX_VALUE;
|
int max = Integer.MAX_VALUE;
|
||||||
int[] dp = new int[n + 1];
|
int[] dp = new int[n + 1];
|
||||||
@ -170,7 +171,9 @@ class Solution {
|
|||||||
}
|
}
|
||||||
//当和为0时,组合的个数为0
|
//当和为0时,组合的个数为0
|
||||||
dp[0] = 0;
|
dp[0] = 0;
|
||||||
|
// 遍历物品
|
||||||
for (int i = 1; i * i <= n; i++) {
|
for (int i = 1; i * i <= n; i++) {
|
||||||
|
// 遍历背包
|
||||||
for (int j = i * i; j <= n; j++) {
|
for (int j = i * i; j <= n; j++) {
|
||||||
if (dp[j - i * i] != max) {
|
if (dp[j - i * i] != max) {
|
||||||
dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
|
dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
|
||||||
@ -180,6 +183,28 @@ class Solution {
|
|||||||
return dp[n];
|
return dp[n];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Solution {
|
||||||
|
// 版本二, 先遍历背包, 再遍历物品
|
||||||
|
public int numSquares(int n) {
|
||||||
|
int max = Integer.MAX_VALUE;
|
||||||
|
int[] dp = new int[n + 1];
|
||||||
|
// 初始化
|
||||||
|
for (int j = 0; j <= n; j++) {
|
||||||
|
dp[j] = max;
|
||||||
|
}
|
||||||
|
// 当和为0时,组合的个数为0
|
||||||
|
dp[0] = 0;
|
||||||
|
// 遍历背包
|
||||||
|
for (int j = 1; j <= n; j++) {
|
||||||
|
// 遍历物品
|
||||||
|
for (int i = 1; i * i <= j; i++) {
|
||||||
|
dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[n];
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Python:
|
Python:
|
||||||
@ -187,7 +212,7 @@ Python:
|
|||||||
```python3
|
```python3
|
||||||
class Solution:
|
class Solution:
|
||||||
def numSquares(self, n: int) -> int:
|
def numSquares(self, n: int) -> int:
|
||||||
'''版本一'''
|
'''版本一,先遍历背包, 再遍历物品'''
|
||||||
# 初始化
|
# 初始化
|
||||||
nums = [i**2 for i in range(1, n + 1) if i**2 <= n]
|
nums = [i**2 for i in range(1, n + 1) if i**2 <= n]
|
||||||
dp = [10**4]*(n + 1)
|
dp = [10**4]*(n + 1)
|
||||||
@ -201,7 +226,7 @@ class Solution:
|
|||||||
return dp[n]
|
return dp[n]
|
||||||
|
|
||||||
def numSquares1(self, n: int) -> int:
|
def numSquares1(self, n: int) -> int:
|
||||||
'''版本二'''
|
'''版本二, 先遍历物品, 再遍历背包'''
|
||||||
# 初始化
|
# 初始化
|
||||||
nums = [i**2 for i in range(1, n + 1) if i**2 <= n]
|
nums = [i**2 for i in range(1, n + 1) if i**2 <= n]
|
||||||
dp = [10**4]*(n + 1)
|
dp = [10**4]*(n + 1)
|
||||||
@ -217,6 +242,22 @@ class Solution:
|
|||||||
Python3:
|
Python3:
|
||||||
```python
|
```python
|
||||||
class Solution:
|
class Solution:
|
||||||
|
'''版本一,先遍历背包, 再遍历物品'''
|
||||||
|
def numSquares(self, n: int) -> int:
|
||||||
|
dp = [n] * (n + 1)
|
||||||
|
dp[0] = 0
|
||||||
|
# 遍历背包
|
||||||
|
for j in range(1, n+1):
|
||||||
|
for i in range(1, n):
|
||||||
|
num = i ** 2
|
||||||
|
if num > j: break
|
||||||
|
# 遍历物品
|
||||||
|
if j - num >= 0:
|
||||||
|
dp[j] = min(dp[j], dp[j - num] + 1)
|
||||||
|
return dp[n]
|
||||||
|
|
||||||
|
class Solution:
|
||||||
|
'''版本二, 先遍历物品, 再遍历背包'''
|
||||||
def numSquares(self, n: int) -> int:
|
def numSquares(self, n: int) -> int:
|
||||||
# 初始化
|
# 初始化
|
||||||
# 组成和的完全平方数的最多个数,就是只用1构成
|
# 组成和的完全平方数的最多个数,就是只用1构成
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
* 1 <= nums.length <= 2500
|
* 1 <= nums.length <= 2500
|
||||||
* -10^4 <= nums[i] <= 104
|
* -10^4 <= nums[i] <= 104
|
||||||
|
|
||||||
|
## 方法一 动态规划
|
||||||
## 思路
|
## 思路
|
||||||
|
|
||||||
最长上升子序列是动规的经典题目,这里dp[i]是可以根据dp[j] (j < i)推导出来的,那么依然用动规五部曲来分析详细一波:
|
最长上升子序列是动规的经典题目,这里dp[i]是可以根据dp[j] (j < i)推导出来的,那么依然用动规五部曲来分析详细一波:
|
||||||
@ -190,10 +190,130 @@ const lengthOfLIS = (nums) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
*复杂度分析*
|
*复杂度分析*
|
||||||
- 时间复杂度:O(nlogn)。数组 nums 的长度为 n,我们依次用数组中的元素去更新 dp 数组,相当于插入最后递增的元素,而更新 dp 数组时需要进行 O(logn) 的二分搜索,所以总时间复杂度为 O(nlogn)。
|
- 时间复杂度:O(n^2)。数组 nums 的长度为 n,我们依次用数组中的元素去遍历 dp 数组,而遍历 dp 数组时需要进行 O(n) 次搜索,所以总时间复杂度为 O(n^2)。
|
||||||
- 空间复杂度:O(n),需要额外使用长度为 n 的 dp 数组。
|
- 空间复杂度:O(n),需要额外使用长度为 n 的 dp 数组。
|
||||||
|
|
||||||
|
|
||||||
|
## 方法二 贪心策略+二分搜索
|
||||||
|
|
||||||
|
使用贪心策略和二分搜索可以进一步将算法时间复杂度将为O(nlogn)。
|
||||||
|
|
||||||
|
## 思路
|
||||||
|
|
||||||
|
为了使得到的子序列尽可能长,我们需要使序列上升得尽可能慢。
|
||||||
|
|
||||||
|
对于长度为n的数组 nums,我们从0到n-1依次遍历数组中的每个元素nums[i],更新在0到i范围内最长上升子序列的长度len,以及 在0到i范围内,上升子序列的长度为1到len时,对应长度子序列最右端的最小值,将结果保存在list中。实际编码过程中,list长度即为len。
|
||||||
|
|
||||||
|
## 可行性
|
||||||
|
当我们遍历完数组nums中第n-1个元素时,list中保存的是0到n-1范围内最长上升子序列的长度,即为所求。
|
||||||
|
|
||||||
|
## 算法复杂度分析
|
||||||
|
1. list中的元素是单调递增的。可以用反证法来证明:假设对于0<=i<j<len,有list[i]>=list[j],那么我们可以在list[j]对应的子序列中删除最后j-i个元素得到长度与list[i]相同的子序列,其最右端的值max<list[j]<=list[i],与list的定义矛盾。
|
||||||
|
|
||||||
|
2. 假设我们已经得到0到i-1范围内对应的list,我们可以在O(logn)的时间复杂度内更新list,得到0到i范围内的list。
|
||||||
|
|
||||||
|
1. if(nums[i]>list[len-1],此时,list中子序列长度为1到len的对应的最右端最小值不变,并新增长度为len+1的子序列,最右端的最小值为nums[i],时间复杂度O(1);
|
||||||
|
|
||||||
|
2. if(nums[i]<=list[len-1]),此时,我们可以在0到len-1范围内找到k,list[k]为>=nums[i]的最小值,由于list单调递增,所以我们可以使用二分搜索在O(logn)的时间复杂度内找到k。
|
||||||
|
1. 对于0<=j<k,list[j]<nums[i]恒成立,对应list[j]的值不需要更新。
|
||||||
|
2. 对于list[k],其值更新为nums[i],因为原本list[k]对应的子序列的倒数第二项的值可以=list[k-1]<nums[i]。
|
||||||
|
3. 对于k<j<=len-1,对应的list[j]不需要更新。因为这些list[j]对应的子序列的倒数第二项的值>nums[i];
|
||||||
|
|
||||||
|
3. 综上,算法时间复杂度为O(nlogn),空间复杂度为O(n),需要O(n)的空间保存list。
|
||||||
|
|
||||||
|
代码如下
|
||||||
|
|
||||||
|
Java
|
||||||
|
```java
|
||||||
|
class Solution {
|
||||||
|
public int lengthOfLIS(int[] nums) {
|
||||||
|
int n = nums.length;
|
||||||
|
if(n==0){return 0;}
|
||||||
|
|
||||||
|
List<Integer> list=new ArrayList<>();
|
||||||
|
list.add(nums[0]);
|
||||||
|
for (int i = 1; i < n; ++i) {
|
||||||
|
if (nums[i] > list.get(list.size()-1)) {
|
||||||
|
list.add(nums[i]);
|
||||||
|
} else {
|
||||||
|
int k=binarySearch(list,nums[i]);
|
||||||
|
list.set(k,nums[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int binarySearch(List<Integer>list, int num){
|
||||||
|
int len=list.size();
|
||||||
|
int l=0,r=len-1,ans=len-1;
|
||||||
|
while(l<=r){
|
||||||
|
int mid=l+(r-l)/2;
|
||||||
|
if(list.get(mid)<num){
|
||||||
|
l=mid+1;
|
||||||
|
}else{
|
||||||
|
r=mid-1;
|
||||||
|
ans=mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
实际运行过程中,list的长度不会超过n,所以我们可以用数组来模拟list,代码如下。
|
||||||
|
|
||||||
|
|
||||||
|
Java
|
||||||
|
```java
|
||||||
|
class Solution {
|
||||||
|
public int lengthOfLIS(int[] nums) {
|
||||||
|
int n = nums.length;
|
||||||
|
if(n==0){return 0;}
|
||||||
|
|
||||||
|
//初始化list,len记录list长度
|
||||||
|
int[] list=new int[n];
|
||||||
|
int len=0;
|
||||||
|
|
||||||
|
//添加元素到list并更新len的值
|
||||||
|
list[len++]=nums[0];
|
||||||
|
|
||||||
|
for (int i = 1; i < n; ++i) {
|
||||||
|
if (nums[i] > list[len-1]) {
|
||||||
|
list[len++]=nums[i];
|
||||||
|
} else {
|
||||||
|
int k=binarySearch(list,len,nums[i]);
|
||||||
|
list[k]=nums[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int binarySearch(int[] list,int len, int num){
|
||||||
|
|
||||||
|
int l=0,r=len-1,ans=len-1;
|
||||||
|
while(l<=r){
|
||||||
|
int mid=l+(r-l)/2;
|
||||||
|
if(list[mid]<num){
|
||||||
|
l=mid+1;
|
||||||
|
}else{
|
||||||
|
r=mid-1;
|
||||||
|
ans=mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||||
|
@ -227,7 +227,34 @@ class Solution:
|
|||||||
return dp[n]
|
return dp[n]
|
||||||
```
|
```
|
||||||
Go:
|
Go:
|
||||||
|
```golang
|
||||||
|
func integerBreak(n int) int {
|
||||||
|
/**
|
||||||
|
动态五部曲
|
||||||
|
1.确定dp下标及其含义
|
||||||
|
2.确定递推公式
|
||||||
|
3.确定dp初始化
|
||||||
|
4.确定遍历顺序
|
||||||
|
5.打印dp
|
||||||
|
**/
|
||||||
|
dp:=make([]int,n+1)
|
||||||
|
dp[1]=1
|
||||||
|
dp[2]=1
|
||||||
|
for i:=3;i<n+1;i++{
|
||||||
|
for j:=1;j<i-1;j++{
|
||||||
|
// i可以差分为i-j和j。由于需要最大值,故需要通过j遍历所有存在的值,取其中最大的值作为当前i的最大值,在求最大值的时候,一个是j与i-j相乘,一个是j与dp[i-j].
|
||||||
|
dp[i]=max(dp[i],max(j*(i-j),j*dp[i-j]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[n]
|
||||||
|
}
|
||||||
|
func max(a,b int) int{
|
||||||
|
if a>b{
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Javascript:
|
Javascript:
|
||||||
```Javascript
|
```Javascript
|
||||||
|
@ -162,21 +162,14 @@ class Solution:
|
|||||||
Do not return anything, modify s in-place instead.
|
Do not return anything, modify s in-place instead.
|
||||||
"""
|
"""
|
||||||
left, right = 0, len(s) - 1
|
left, right = 0, len(s) - 1
|
||||||
while(left < right):
|
|
||||||
|
# 该方法已经不需要判断奇偶数,经测试后时间空间复杂度比用 for i in range(right//2)更低
|
||||||
|
# 推荐该写法,更加通俗易懂
|
||||||
|
while left < right:
|
||||||
s[left], s[right] = s[right], s[left]
|
s[left], s[right] = s[right], s[left]
|
||||||
left += 1
|
left += 1
|
||||||
right -= 1
|
right -= 1
|
||||||
|
|
||||||
# 下面的写法更加简洁,但是都是同样的算法
|
|
||||||
# class Solution:
|
|
||||||
# def reverseString(self, s: List[str]) -> None:
|
|
||||||
# """
|
|
||||||
# Do not return anything, modify s in-place instead.
|
|
||||||
# """
|
|
||||||
# 不需要判别是偶数个还是奇数个序列,因为奇数个的时候,中间那个不需要交换就可
|
|
||||||
# for i in range(len(s)//2):
|
|
||||||
# s[i], s[len(s)-1-i] = s[len(s)-1-i], s[i]
|
|
||||||
# return s
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Go:
|
Go:
|
||||||
|
@ -143,6 +143,26 @@ func intersection(nums1 []int, nums2 []int) []int {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
```golang
|
||||||
|
//优化版,利用set,减少count统计
|
||||||
|
func intersection(nums1 []int, nums2 []int) []int {
|
||||||
|
set:=make(map[int]struct{},0)
|
||||||
|
res:=make([]int,0)
|
||||||
|
for _,v:=range nums1{
|
||||||
|
if _,ok:=set[v];!ok{
|
||||||
|
set[v]=struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _,v:=range nums2{
|
||||||
|
//如果存在于上一个数组中,则加入结果集,并清空该set值
|
||||||
|
if _,ok:=set[v];ok{
|
||||||
|
res=append(res,v)
|
||||||
|
delete(set, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
javaScript:
|
javaScript:
|
||||||
|
|
||||||
|
@ -155,34 +155,27 @@ class Solution {
|
|||||||
|
|
||||||
Python:
|
Python:
|
||||||
```python
|
```python
|
||||||
|
class Solution:
|
||||||
class Solution(object):
|
def reverseStr(self, s: str, k: int) -> str:
|
||||||
def reverseStr(self, s, k):
|
|
||||||
"""
|
"""
|
||||||
:type s: str
|
1. 使用range(start, end, step)来确定需要调换的初始位置
|
||||||
:type k: int
|
2. 对于字符串s = 'abc',如果使用s[0:999] ===> 'abc'。字符串末尾如果超过最大长度,则会返回至字符串最后一个值,这个特性可以避免一些边界条件的处理。
|
||||||
:rtype: str
|
3. 用切片整体替换,而不是一个个替换.
|
||||||
"""
|
"""
|
||||||
from functools import reduce
|
def reverse_substring(text):
|
||||||
# turn s into a list
|
left, right = 0, len(text) - 1
|
||||||
s = list(s)
|
|
||||||
|
|
||||||
# another way to simply use a[::-1], but i feel this is easier to understand
|
|
||||||
def reverse(s):
|
|
||||||
left, right = 0, len(s) - 1
|
|
||||||
while left < right:
|
while left < right:
|
||||||
s[left], s[right] = s[right], s[left]
|
text[left], text[right] = text[right], text[left]
|
||||||
left += 1
|
left += 1
|
||||||
right -= 1
|
right -= 1
|
||||||
return s
|
return text
|
||||||
|
|
||||||
# make sure we reverse each 2k elements
|
res = list(s)
|
||||||
for i in range(0, len(s), 2*k):
|
|
||||||
s[i:(i+k)] = reverse(s[i:(i+k)])
|
|
||||||
|
|
||||||
# combine list into str.
|
for cur in range(0, len(s), 2 * k):
|
||||||
return reduce(lambda a, b: a+b, s)
|
res[cur: cur + k] = reverse_substring(res[cur: cur + k])
|
||||||
|
|
||||||
|
return ''.join(res)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -949,6 +949,89 @@ class MyLinkedList {
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Swift:
|
||||||
|
|
||||||
|
```swift
|
||||||
|
class MyLinkedList {
|
||||||
|
var dummyHead: ListNode<Int>?
|
||||||
|
var size: Int
|
||||||
|
|
||||||
|
init() {
|
||||||
|
dummyHead = ListNode(0)
|
||||||
|
size = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func get(_ index: Int) -> Int {
|
||||||
|
if index >= size || index < 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
var curNode = dummyHead?.next
|
||||||
|
var curIndex = index
|
||||||
|
|
||||||
|
while curIndex > 0 {
|
||||||
|
curNode = curNode?.next
|
||||||
|
curIndex -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return curNode?.value ?? -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func addAtHead(_ val: Int) {
|
||||||
|
let newHead = ListNode(val)
|
||||||
|
newHead.next = dummyHead?.next
|
||||||
|
dummyHead?.next = newHead
|
||||||
|
size += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func addAtTail(_ val: Int) {
|
||||||
|
let newNode = ListNode(val)
|
||||||
|
var curNode = dummyHead
|
||||||
|
while curNode?.next != nil {
|
||||||
|
curNode = curNode?.next
|
||||||
|
}
|
||||||
|
|
||||||
|
curNode?.next = newNode
|
||||||
|
size += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func addAtIndex(_ index: Int, _ val: Int) {
|
||||||
|
if index > size {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let newNode = ListNode(val)
|
||||||
|
var curNode = dummyHead
|
||||||
|
var curIndex = index
|
||||||
|
|
||||||
|
while curIndex > 0 {
|
||||||
|
curNode = curNode?.next
|
||||||
|
curIndex -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
newNode.next = curNode?.next
|
||||||
|
curNode?.next = newNode
|
||||||
|
size += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteAtIndex(_ index: Int) {
|
||||||
|
if index >= size || index < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var curNode = dummyHead
|
||||||
|
for _ in 0..<index {
|
||||||
|
curNode = curNode?.next
|
||||||
|
}
|
||||||
|
|
||||||
|
curNode?.next = curNode?.next?.next
|
||||||
|
size -= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||||
|
@ -233,7 +233,41 @@ var commonChars = function (words) {
|
|||||||
return res
|
return res
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
GO
|
||||||
|
```golang
|
||||||
|
func commonChars(words []string) []string {
|
||||||
|
length:=len(words)
|
||||||
|
fre:=make([][]int,0)//统计每个字符串的词频
|
||||||
|
res:=make([]string,0)
|
||||||
|
//统计词频
|
||||||
|
for i:=0;i<length;i++{
|
||||||
|
var row [26]int//存放该字符串的词频
|
||||||
|
for j:=0;j<len(words[i]);j++{
|
||||||
|
row[words[i][j]-97]++
|
||||||
|
}
|
||||||
|
fre=append(fre,row[:])
|
||||||
|
}
|
||||||
|
//查找一列的最小值
|
||||||
|
for j:=0;j<len(fre[0]);j++{
|
||||||
|
pre:=fre[0][j]
|
||||||
|
for i:=0;i<len(fre);i++{
|
||||||
|
pre=min(pre,fre[i][j])
|
||||||
|
}
|
||||||
|
//将该字符添加到结果集(按照次数)
|
||||||
|
tmpString:=string(j+97)
|
||||||
|
for i:=0;i<pre;i++{
|
||||||
|
res=append(res,tmpString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
func min(a,b int)int{
|
||||||
|
if a>b{
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
```
|
||||||
-----------------------
|
-----------------------
|
||||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||||
|
@ -197,15 +197,38 @@ class Solution {
|
|||||||
|
|
||||||
Python:
|
Python:
|
||||||
```python3
|
```python3
|
||||||
|
# 方法一,使用栈,推荐!
|
||||||
class Solution:
|
class Solution:
|
||||||
def removeDuplicates(self, s: str) -> str:
|
def removeDuplicates(self, s: str) -> str:
|
||||||
t = list()
|
res = list()
|
||||||
for i in s:
|
for item in s:
|
||||||
if t and t[-1] == i:
|
if res and res[-1] == item:
|
||||||
t.pop(-1)
|
res.pop()
|
||||||
else:
|
else:
|
||||||
t.append(i)
|
res.append(item)
|
||||||
return "".join(t) # 字符串拼接
|
return "".join(res) # 字符串拼接
|
||||||
|
```
|
||||||
|
|
||||||
|
```python3
|
||||||
|
# 方法二,使用双指针模拟栈,如果不让用栈可以作为备选方法。
|
||||||
|
class Solution:
|
||||||
|
def removeDuplicates(self, s: str) -> str:
|
||||||
|
res = list(s)
|
||||||
|
slow = fast = 0
|
||||||
|
length = len(res)
|
||||||
|
|
||||||
|
while fast < length:
|
||||||
|
# 如果一样直接换,不一样会把后面的填在slow的位置
|
||||||
|
res[slow] = res[fast]
|
||||||
|
|
||||||
|
# 如果发现和前一个一样,就退一格指针
|
||||||
|
if slow > 0 and res[slow] == res[slow - 1]:
|
||||||
|
slow -= 1
|
||||||
|
else:
|
||||||
|
slow += 1
|
||||||
|
fast += 1
|
||||||
|
|
||||||
|
return ''.join(res[0: slow])
|
||||||
```
|
```
|
||||||
|
|
||||||
Go:
|
Go:
|
||||||
|
@ -202,45 +202,27 @@ func replaceSpace(s string) string {
|
|||||||
|
|
||||||
python:
|
python:
|
||||||
```python
|
```python
|
||||||
class Solution(object):
|
class Solution:
|
||||||
def replaceSpace(self, s):
|
def replaceSpace(self, s: str) -> str:
|
||||||
"""
|
counter = s.count(' ')
|
||||||
:type s: str
|
|
||||||
:rtype: str
|
|
||||||
"""
|
|
||||||
list_s = list(s)
|
|
||||||
|
|
||||||
# 记录原本字符串的长度
|
res = list(s)
|
||||||
original_end = len(s)
|
# 每碰到一个空格就多拓展两个格子,1 + 2 = 3个位置存’%20‘
|
||||||
|
res.extend([' '] * counter * 2)
|
||||||
|
|
||||||
# 将空格改成%20 使得字符串总长增长 2n,n为原本空格数量。
|
# 原始字符串的末尾,拓展后的末尾
|
||||||
# 所以记录空格数量就可以得到目标字符串的长度
|
left, right = len(s) - 1, len(res) - 1
|
||||||
n_space = 0
|
|
||||||
for ss in s:
|
|
||||||
if ss == ' ':
|
|
||||||
n_space += 1
|
|
||||||
|
|
||||||
list_s += ['0'] * 2 * n_space
|
|
||||||
|
|
||||||
# 设置左右指针位置
|
|
||||||
left, right = original_end - 1, len(list_s) - 1
|
|
||||||
|
|
||||||
# 循环直至左指针越界
|
|
||||||
while left >= 0:
|
while left >= 0:
|
||||||
if list_s[left] == ' ':
|
if res[left] != ' ':
|
||||||
list_s[right] = '0'
|
res[right] = res[left]
|
||||||
list_s[right - 1] = '2'
|
|
||||||
list_s[right - 2] = '%'
|
|
||||||
right -= 3
|
|
||||||
else:
|
|
||||||
list_s[right] = list_s[left]
|
|
||||||
right -= 1
|
right -= 1
|
||||||
|
else:
|
||||||
|
# [right - 2, right), 左闭右开
|
||||||
|
res[right - 2: right + 1] = '%20'
|
||||||
|
right -= 3
|
||||||
left -= 1
|
left -= 1
|
||||||
|
return ''.join(res)
|
||||||
# 将list变回str,输出
|
|
||||||
s = ''.join(list_s)
|
|
||||||
return s
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -125,24 +125,45 @@ python:
|
|||||||
class Solution:
|
class Solution:
|
||||||
def reverseLeftWords(self, s: str, n: int) -> str:
|
def reverseLeftWords(self, s: str, n: int) -> str:
|
||||||
return s[n:] + s[0:n]
|
return s[n:] + s[0:n]
|
||||||
|
```
|
||||||
|
```python
|
||||||
# 方法二:也可以使用上文描述的方法,有些面试中不允许使用切片,那就使用上文作者提到的方法
|
# 方法二:也可以使用上文描述的方法,有些面试中不允许使用切片,那就使用上文作者提到的方法
|
||||||
# class Solution:
|
class Solution:
|
||||||
# def reverseLeftWords(self, s: str, n: int) -> str:
|
def reverseLeftWords(self, s: str, n: int) -> str:
|
||||||
# s = list(s)
|
s = list(s)
|
||||||
# s[0:n] = list(reversed(s[0:n]))
|
s[0:n] = list(reversed(s[0:n]))
|
||||||
# s[n:] = list(reversed(s[n:]))
|
s[n:] = list(reversed(s[n:]))
|
||||||
# s.reverse()
|
s.reverse()
|
||||||
|
|
||||||
# return "".join(s)
|
return "".join(s)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 方法三:如果连reversed也不让使用,那么自己手写一个
|
||||||
|
class Solution:
|
||||||
|
def reverseLeftWords(self, s: str, n: int) -> str:
|
||||||
|
def reverse_sub(lst, left, right):
|
||||||
|
while left < right:
|
||||||
|
lst[left], lst[right] = lst[right], lst[left]
|
||||||
|
left += 1
|
||||||
|
right -= 1
|
||||||
|
|
||||||
|
res = list(s)
|
||||||
|
end = len(res) - 1
|
||||||
|
reverse_sub(res, 0, n - 1)
|
||||||
|
reverse_sub(res, n, end)
|
||||||
|
reverse_sub(res, 0, end)
|
||||||
|
return ''.join(res)
|
||||||
|
|
||||||
|
# 同方法二
|
||||||
# 时间复杂度:O(n)
|
# 时间复杂度:O(n)
|
||||||
# 空间复杂度:O(n),python的string为不可变,需要开辟同样大小的list空间来修改
|
# 空间复杂度:O(n),python的string为不可变,需要开辟同样大小的list空间来修改
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```python 3
|
```python 3
|
||||||
#方法三:考虑不能用切片的情况下,利用模+下标实现
|
#方法四:考虑不能用切片的情况下,利用模+下标实现
|
||||||
class Solution:
|
class Solution:
|
||||||
def reverseLeftWords(self, s: str, n: int) -> str:
|
def reverseLeftWords(self, s: str, n: int) -> str:
|
||||||
new_s = ''
|
new_s = ''
|
||||||
|
@ -103,7 +103,7 @@ dp[0][j],即:i为0,存放编号0的物品的时候,各个容量的背包
|
|||||||
|
|
||||||
那么很明显当 j < weight[0]的时候,dp[0][j] 应该是 0,因为背包容量比编号0的物品重量还小。
|
那么很明显当 j < weight[0]的时候,dp[0][j] 应该是 0,因为背包容量比编号0的物品重量还小。
|
||||||
|
|
||||||
当j >= weight[0]是,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品。
|
当j >= weight[0]时,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品。
|
||||||
|
|
||||||
代码初始化如下:
|
代码初始化如下:
|
||||||
```
|
```
|
||||||
|
Reference in New Issue
Block a user