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

This commit is contained in:
youngyangyang04
2021-09-09 22:15:30 +08:00
21 changed files with 636 additions and 6 deletions

View File

@ -434,6 +434,46 @@ class Solution {
}
```
Swift:
```swift
// 双指针法
func threeSum(_ nums: [Int]) -> [[Int]] {
var res = [[Int]]()
var sorted = nums
sorted.sort()
for i in 0 ..< sorted.count {
if sorted[i] > 0 {
return res
}
if i > 0 && sorted[i] == sorted[i - 1] {
continue
}
var left = i + 1
var right = sorted.count - 1
while left < right {
let sum = sorted[i] + sorted[left] + sorted[right]
if sum < 0 {
left += 1
} else if sum > 0 {
right -= 1
} else {
res.append([sorted[i], sorted[left], sorted[right]])
while left < right && sorted[left] == sorted[left + 1] {
left += 1
}
while left < right && sorted[right] == sorted[right - 1] {
right -= 1
}
left += 1
right -= 1
}
}
}
return res
}
```
-----------------------
* 作者微信[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)

View File

@ -354,6 +354,54 @@ class Solution {
}
```
Swift:
```swift
func fourSum(_ nums: [Int], _ target: Int) -> [[Int]] {
var res = [[Int]]()
var sorted = nums
sorted.sort()
for k in 0 ..< sorted.count {
// 这种剪枝不行,target可能是负数
// if sorted[k] > target {
// return res
// }
// 去重
if k > 0 && sorted[k] == sorted[k - 1] {
continue
}
let target2 = target - sorted[k]
for i in (k + 1) ..< sorted.count {
if i > (k + 1) && sorted[i] == sorted[i - 1] {
continue
}
var left = i + 1
var right = sorted.count - 1
while left < right {
let sum = sorted[i] + sorted[left] + sorted[right]
if sum < target2 {
left += 1
} else if sum > target2 {
right -= 1
} else {
res.append([sorted[k], sorted[i], sorted[left], sorted[right]])
while left < right && sorted[left] == sorted[left + 1] {
left += 1
}
while left < right && sorted[right] == sorted[right - 1] {
right -= 1
}
// 找到答案 双指针同时收缩
left += 1
right -= 1
}
}
}
}
return res
}
```
-----------------------
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
* B站视频[代码随想录](https://space.bilibili.com/525438321)

View File

@ -391,6 +391,7 @@ class Solution {
}
}
```
动态规划法
```java
class Solution {
@ -418,6 +419,54 @@ class Solution {
}
}
```
单调栈法
```java
class Solution {
public int trap(int[] height){
int size = height.length;
if (size <= 2) return 0;
// in the stack, we push the index of array
// using height[] to access the real height
Stack<Integer> stack = new Stack<Integer>();
stack.push(0);
int sum = 0;
for (int index = 1; index < size; index++){
int stackTop = stack.peek();
if (height[index] < height[stackTop]){
stack.push(index);
}else if (height[index] == height[stackTop]){
// 因为相等的相邻墙左边一个是不可能存放雨水的所以pop左边的index, push当前的index
stack.pop();
stack.push(index);
}else{
//pop up all lower value
int heightAtIdx = height[index];
while (!stack.isEmpty() && (heightAtIdx > height[stackTop])){
int mid = stack.pop();
if (!stack.isEmpty()){
int left = stack.peek();
int h = Math.min(height[left], height[index]) - height[mid];
int w = index - left - 1;
int hold = h * w;
if (hold > 0) sum += hold;
stackTop = stack.peek();
}
}
stack.push(index);
}
}
return sum;
}
}
```
Python:
双指针法

View File

@ -228,6 +228,50 @@ class Solution {
}
```
单调栈
```java
class Solution {
int largestRectangleArea(int[] heights) {
Stack<Integer> st = new Stack<Integer>();
// 数组扩容,在头和尾各加入一个元素
int [] newHeights = new int[heights.length + 2];
newHeights[0] = 0;
newHeights[newHeights.length - 1] = 0;
for (int index = 0; index < heights.length; index++){
newHeights[index + 1] = heights[index];
}
heights = newHeights;
st.push(0);
int result = 0;
// 第一个元素已经入栈从下表1开始
for (int i = 1; i < heights.length; i++) {
// 注意heights[i] 是和heights[st.top()] 比较 st.top()是下表
if (heights[i] > heights[st.peek()]) {
st.push(i);
} else if (heights[i] == heights[st.peek()]) {
st.pop(); // 这个可以加,可以不加,效果一样,思路不同
st.push(i);
} else {
while (heights[i] < heights[st.peek()]) { // 注意是while
int mid = st.peek();
st.pop();
int left = st.peek();
int right = i;
int w = right - left - 1;
int h = heights[mid];
result = Math.max(result, w * h);
}
st.push(i);
}
}
return result;
}
}
```
Python:
动态规划

View File

@ -607,6 +607,7 @@ class Solution {
for (int i = inLeft; i < inRight; i++) {
if (inorder[i] == rootVal) {
rootIndex = i;
break;
}
}
// 根据rootIndex划分左右子树

View File

@ -411,6 +411,31 @@ class solution {
}
```
```java
// 解法2
class Solution {
List<List<Integer>> result;
LinkedList<Integer> path;
public List<List<Integer>> pathSum (TreeNode root,int targetSum) {
result = new LinkedList<>();
path = new LinkedList<>();
travesal(root, targetSum);
return result;
}
private void travesal(TreeNode root, int count) {
if (root == null) return;
path.offer(root.val);
count -= root.val;
if (root.left == null && root.right == null && count == 0) {
result.add(new LinkedList<>(path));
}
travesal(root.left, count);
travesal(root.right, count);
path.removeLast(); // 回溯
}
}
```
## python
0112.路径总和

View File

@ -164,6 +164,52 @@ public:
Java
```java
class Solution {
List<Integer> path = new ArrayList<>();
int res = 0;
public int sumNumbers(TreeNode root) {
// 如果节点为0那么就返回0
if (root == null) return 0;
// 首先将根节点放到集合中
path.add(root.val);
// 开始递归
recur(root);
return res;
}
public void recur(TreeNode root){
if (root.left == null && root.right == null) {
// 当是叶子节点的时候,开始处理
res += listToInt(path);
return;
}
if (root.left != null){
// 注意有回溯
path.add(root.left.val);
recur(root.left);
path.remove(path.size() - 1);
}
if (root.right != null){
// 注意有回溯
path.add(root.right.val);
recur(root.right);
path.remove(path.size() - 1);
}
return;
}
public int listToInt(List<Integer> path){
int sum = 0;
for (Integer num:path){
// sum * 10 表示进位
sum = sum * 10 + num;
}
return sum;
}
}
```
Python
```python3
class Solution:

View File

@ -177,6 +177,7 @@ public:
Java
```java
// 方法三
public class ReorderList {
public void reorderList(ListNode head) {
ListNode fast = head, slow = head;
@ -219,6 +220,76 @@ public class ReorderList {
return headNode.next;
}
}
-------------------------------------------------------------------------
// 方法一 Java实现使用数组存储节点
class Solution {
public void reorderList(ListNode head) {
// 双指针的做法
ListNode cur = head;
// ArrayList底层是数组可以使用下标随机访问
List<ListNode> list = new ArrayList<>();
while (cur != null){
list.add(cur);
cur = cur.next;
}
cur = head; // 重新回到头部
int l = 1, r = list.size() - 1; // 注意左边是从1开始
int count = 0;
while (l <= r){
if (count % 2 == 0){
// 偶数
cur.next = list.get(r);
r--;
}else {
// 奇数
cur.next = list.get(l);
l++;
}
// 每一次指针都需要移动
cur = cur.next;
count++;
}
// 当是偶数的话,需要做额外处理
if (list.size() % 2== 0){
cur.next = list.get(l);
cur = cur.next;
}
// 注意结尾要结束一波
cur.next = null;
}
}
-------------------------------------------------------------------------
// 方法二:使用双端队列,简化了数组的操作,代码相对于前者更简洁(避免一些边界条件)
class Solution {
public void reorderList(ListNode head) {
// 使用双端队列的方法来解决
Deque<ListNode> de = new LinkedList<>();
// 这里是取head的下一个节点head不需要再入队了避免造成重复
ListNode cur = head.next;
while (cur != null){
de.offer(cur);
cur = cur.next;
}
cur = head; // 回到头部
int count = 0;
while (!de.isEmpty()){
if (count % 2 == 0){
// 偶数,取出队列右边尾部的值
cur.next = de.pollLast();
}else {
// 奇数,取出队列左边头部的值
cur.next = de.poll();
}
cur = cur.next;
count++;
}
cur.next = null;
}
}
```
Python

View File

@ -234,7 +234,15 @@ public:
## Java
递归法:
```java
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left, p, q);
if (root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right, p, q);
return root;
}
}
```
迭代法:
```java

View File

@ -367,6 +367,43 @@ class Solution {
}
}
```
```java
// 解法2
class Solution {
/**
* 迭代法
*/
public List<String> binaryTreePaths(TreeNode root) {
List<String> result = new ArrayList<>();
if (root == null)
return result;
Stack<Object> stack = new Stack<>();
// 节点和路径同时入栈
stack.push(root);
stack.push(root.val + "");
while (!stack.isEmpty()) {
// 节点和路径同时出栈
String path = (String) stack.pop();
TreeNode node = (TreeNode) stack.pop();
// 若找到叶子节点
if (node.left == null && node.right == null) {
result.add(path);
}
//右子节点不为空
if (node.right != null) {
stack.push(node.right);
stack.push(path + "->" + node.right.val);
}
//左子节点不为空
if (node.left != null) {
stack.push(node.left);
stack.push(path + "->" + node.left.val);
}
}
return result;
}
}
```
Python
```Python

View File

@ -39,7 +39,7 @@
1. dp[i]的定义
**dp[i]表示i之前包括i的最长上升子序列**
**dp[i]表示i之前包括i的最长上升子序列的长度**
2. 状态转移方程

View File

@ -209,8 +209,13 @@ Python
```python
class Solution:
def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
# 先按照h维度的身高顺序从高到低排序。确定第一个维度
# lambda返回的是一个元组当-x[0](维度h相同时再根据x[1]维度k从小到大排序
people.sort(key=lambda x: (-x[0], x[1]))
que = []
# 根据每个元素的第二个维度k贪心算法进行插入
# people已经排序过了同一高度时k值小的排前面。
for p in people:
que.insert(p[1], p)
return que

View File

@ -118,10 +118,25 @@ public:
if (root == nullptr) return root; // 第一种情况:没找到删除的节点,遍历到空节点直接返回了
if (root->val == key) {
// 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
if (root->left == nullptr && root->right == nullptr) {
///! 内存释放
delete root;
return nullptr;
}
// 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点
if (root->left == nullptr) return root->right;
else if (root->left == nullptr) {
auto retNode = root->right;
///! 内存释放
delete root;
return retNode;
}
// 第四种情况:其右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
else if (root->right == nullptr) return root->left;
else if (root->right == nullptr) {
auto retNode = root->left;
///! 内存释放
delete root;
return retNode;
}
// 第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到删除节点的右子树的最左面节点的左孩子的位置
// 并返回删除节点右孩子为新的根节点。
else {
@ -278,6 +293,32 @@ class Solution {
}
}
```
```java
// 解法2
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) return root;
if (root.val == key) {
if (root.left == null) {
return root.right;
} else if (root.right == null) {
return root.left;
} else {
TreeNode cur = root.right;
while (cur.left != null) {
cur = cur.left;
}
cur.left = root.left;
root = root.right;
return root;
}
}
if (root.val > key) root.left = deleteNode(root.left, key);
if (root.val < key) root.right = deleteNode(root.right, key);
return root;
}
}
```
## Python

View File

@ -429,6 +429,44 @@ class Solution {
}
}
```
迭代法
```java
class Solution {
public int[] findMode(TreeNode root) {
TreeNode pre = null;
Stack<TreeNode> stack = new Stack<>();
List<Integer> result = new ArrayList<>();
int maxCount = 0;
int count = 0;
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
if (cur != null) {
stack.push(cur);
cur =cur.left;
}else {
cur = stack.pop();
// 计数
if (pre == null || cur.val != pre.val) {
count = 1;
}else {
count++;
}
// 更新结果
if (count > maxCount) {
maxCount = count;
result.clear();
result.add(cur.val);
}else if (count == maxCount) {
result.add(cur.val);
}
pre = cur;
cur = cur.right;
}
}
return result.stream().mapToInt(Integer::intValue).toArray();
}
}
```
## Python

View File

@ -132,6 +132,26 @@ class Solution:
return dp
```
Go:
```go
func nextGreaterElements(nums []int) []int {
length := len(nums)
result := make([]int,length,length)
for i:=0;i<len(result);i++{
result[i] = -1
}
//单调递减,存储数组下标索引
stack := make([]int,0)
for i:=0;i<length*2;i++{
for len(stack)>0&&nums[i%length]>nums[stack[len(stack)-1]]{
index := stack[len(stack)-1]
stack = stack[:len(stack)-1] // pop
result[index] = nums[i%length]
}
stack = append(stack,i%length)
}
return result
}
```
JavaScript:

View File

@ -171,7 +171,34 @@ class Solution {
}
}
```
迭代法-中序遍历
```java
class Solution {
TreeNode pre;
Stack<TreeNode> stack;
public int getMinimumDifference(TreeNode root) {
if (root == null) return 0;
stack = new Stack<>();
TreeNode cur = root;
int result = Integer.MAX_VALUE;
while (cur != null || !stack.isEmpty()) {
if (cur != null) {
stack.push(cur); // 将访问的节点放进栈
cur = cur.left; // 左
}else {
cur = stack.pop();
if (pre != null) { // 中
result = Math.min(result, cur.val - pre.val);
}
pre = cur;
cur = cur.right; // 右
}
}
return result;
}
}
```
## Python
递归

View File

@ -274,7 +274,7 @@ class Solution {
```Java
class Solution {
// 迭代
// 使用栈迭代
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if (root1 == null) {
return root2;
@ -310,6 +310,43 @@ class Solution {
}
}
```
```java
class Solution {
// 使用队列迭代
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if (root1 == null) return root2;
if (root2 ==null) return root1;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root1);
queue.offer(root2);
while (!queue.isEmpty()) {
TreeNode node1 = queue.poll();
TreeNode node2 = queue.poll();
// 此时两个节点一定不为空val相加
node1.val = node1.val + node2.val;
// 如果两棵树左节点都不为空,加入队列
if (node1.left != null && node2.left != null) {
queue.offer(node1.left);
queue.offer(node2.left);
}
// 如果两棵树右节点都不为空,加入队列
if (node1.right != null && node2.right != null) {
queue.offer(node1.right);
queue.offer(node2.right);
}
// 若node1的左节点为空直接赋值
if (node1.left == null && node2.left != null) {
node1.left = node2.left;
}
// 若node2的左节点为空直接赋值
if (node1.right == null && node2.right != null) {
node1.right = node2.right;
}
}
return root1;
}
}
```
## Python

View File

@ -193,6 +193,26 @@ class Solution:
hash[i] -= 1
return result
```
Python 3 使用collections.Counter
```python
class Solution:
def commonChars(self, words: List[str]) -> List[str]:
tmp = collections.Counter(words[0])
l = []
for i in range(1,len(words)):
# 使用 & 取交集
tmp = tmp & collections.Counter(words[i])
# 剩下的就是每个单词都出现的字符(键),个数(值)
for j in tmp:
v = tmp[j]
while(v):
l.append(j)
v -= 1
return l
```
javaScript
```js
var commonChars = function (words) {

View File

@ -123,6 +123,31 @@ public:
## Java
```java
class Solution {
private int cntInt(int val){
int count = 0;
while(val > 0) {
val = val & (val - 1);
count ++;
}
return count;
}
public int[] sortByBits(int[] arr) {
return Arrays.stream(arr).boxed()
.sorted(new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
int cnt1 = cntInt(o1);
int cnt2 = cntInt(o2);
return (cnt1 == cnt2) ? Integer.compare(o1, o2) : Integer.compare(cnt1, cnt2);
}
})
.mapToInt(Integer::intValue)
.toArray();
}
}
```

View File

@ -360,8 +360,56 @@ var postorderTraversal = function(root) {
};
```
C:
```c
//前序遍历:
void preOrderTraversal(struct TreeNode* root, int* ret, int* returnSize) {
if(root == NULL)
return;
ret[(*returnSize)++] = root->val;
preOrderTraverse(root->left, ret, returnSize);
preOrderTraverse(root->right, ret, returnSize);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
int* ret = (int*)malloc(sizeof(int) * 100);
*returnSize = 0;
preOrderTraversal(root, ret, returnSize);
return ret;
}
//中序遍历:
void inOrder(struct TreeNode* node, int* ret, int* returnSize) {
if(!node)
return;
inOrder(node->left, ret, returnSize);
ret[(*returnSize)++] = node->val;
inOrder(node->right, ret, returnSize);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
int* ret = (int*)malloc(sizeof(int) * 100);
*returnSize = 0;
inOrder(root, ret, returnSize);
return ret;
}
//后序遍历:
void postOrder(struct TreeNode* node, int* ret, int* returnSize) {
if(node == NULL)
return;
postOrder(node->left, ret, returnSize);
postOrder(node->right, ret, returnSize);
ret[(*returnSize)++] = node->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize){
int* ret= (int*)malloc(sizeof(int) * 100);
*returnSize = 0;
postOrder(root, ret, returnSize);
return ret;
}
```
-----------------------
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)

View File

@ -166,7 +166,7 @@ void time_consumption() {
system_clock::now().time_since_epoch()
);
fibonacci_3(0, 1, n);
fibonacci_3(1, 1, n);
milliseconds end_time = duration_cast<milliseconds >(
system_clock::now().time_since_epoch()