This commit is contained in:
youngyangyang04
2021-11-11 01:35:37 +08:00
30 changed files with 944 additions and 102 deletions

View File

@ -120,8 +120,50 @@ class Solution {
```
## Python
>直接使用sorted()不符合题意
```python
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
for i in range(len(nums)-1, -1, -1):
for j in range(len(nums)-1, i, -1):
if nums[j] > nums[i]:
nums[j], nums[i] = nums[i], nums[j]
nums[i+1:len(nums)] = sorted(nums[i+1:len(nums)])
return
nums.sort()
```
>另一种思路
```python
class Solution:
'''
抛砖引玉因题目要求“必须原地修改只允许使用额外常数空间”python内置sorted函数以及数组切片+sort()无法使用。
故选择另一种算法暂且提供一种python思路
'''
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
length = len(nums)
for i in range(length-1, 0, -1):
if nums[i-1] < nums[i]:
for j in range(length-1, 0, -1):
if nums[j] > nums[i-1]:
nums[i-1], nums[j] = nums[j], nums[i-1]
break
self.reverse(nums, i, length-1)
break
else:
# 若正常结束循环,则对原数组直接翻转
self.reverse(nums, 0, length-1)
def reverse(self, nums: List[int], low: int, high: int) -> None:
while low < high:
nums[low], nums[high] = nums[high], nums[low]
low += 1
high -= 1
```
## Go

View File

@ -161,6 +161,25 @@ class Solution {
}
```
```java
// DP 方法
class Solution {
public int maxSubArray(int[] nums) {
int ans = Integer.MIN_VALUE;
int[] dp = new int[nums.length];
dp[0] = nums[0];
ans = dp[0];
for (int i = 1; i < nums.length; i++){
dp[i] = Math.max(dp[i-1] + nums[i], nums[i]);
ans = Math.max(dp[i], ans);
}
return ans;
}
}
```
Python
```python
class Solution:

View File

@ -92,8 +92,8 @@ class Solution {
if (nums.length == 1) {
return true;
}
//覆盖范围
int coverRange = nums[0];
//覆盖范围, 初始覆盖范围应该是0因为下面的迭代是从下标0开始的
int coverRange = 0;
//在覆盖范围内更新最大的覆盖范围
for (int i = 0; i <= coverRange; i++) {
coverRange = Math.max(coverRange, i + nums[i]);

View File

@ -312,6 +312,24 @@ class solution {
```
### 559.n叉树的最大深度
```java
class Solution {
/*递归法后序遍历求root节点的高度*/
public int maxDepth(Node root) {
if (root == null) return 0;
int depth = 0;
if (root.children != null){
for (Node child : root.children){
depth = Math.max(depth, maxDepth(child));
}
}
return depth + 1; //中节点
}
}
```
```java
class solution {
/**

View File

@ -792,16 +792,13 @@ func findRootIndex(target int,inorder []int) int{
```javascript
var buildTree = function(inorder, postorder) {
if (!postorder.length) return null
let root = new TreeNode(postorder[postorder.length - 1])
let index = inorder.findIndex(number => number === root.val)
root.left = buildTree(inorder.slice(0, index), postorder.slice(0, index))
root.right = buildTree(inorder.slice(index + 1, inorder.length), postorder.slice(index, postorder.length - 1))
return root
if (!preorder.length) return null;
const rootVal = postorder.pop(); // 从后序遍历的数组中获取中间节点的值, 即数组最后一个值
let rootIndex = inorder.indexOf(rootVal); // 获取中间节点在中序遍历中的下标
const root = new TreeNode(rootVal); // 创建中间节点
root.left = buildTree(inorder.slice(0, rootIndex), postorder.slice(0, rootIndex)); // 创建左节点
root.right = buildTree(inorder.slice(rootIndex + 1), postorder.slice(rootIndex)); // 创建右节点
return root;
};
```
@ -809,13 +806,13 @@ var buildTree = function(inorder, postorder) {
```javascript
var buildTree = function(preorder, inorder) {
if(!preorder.length)
return null;
let root = new TreeNode(preorder[0]);
let mid = inorder.findIndex((number) => number === root.val);
root.left = buildTree(preorder.slice(1, mid + 1), inorder.slice(0, mid));
root.right = buildTree(preorder.slice(mid + 1, preorder.length), inorder.slice(mid + 1, inorder.length));
return root;
if (!preorder.length) return null;
const rootVal = preorder.shift(); // 从前序遍历的数组中获取中间节点的值, 即数组第一个值
const index = inorder.indexOf(rootVal); // 获取中间节点在中序遍历中的下标
const root = new TreeNode(rootVal); // 创建中间节点
root.left = buildTree(preorder.slice(0, index), inorder.slice(0, index)); // 创建左节点
root.right = buildTree(preorder.slice(index), inorder.slice(index + 1)); // 创建右节点
return root;
};
```

View File

@ -375,8 +375,25 @@ var sortedArrayToBST = function (nums) {
};
```
## C
递归
```c
struct TreeNode* traversal(int* nums, int left, int right) {
if (left > right)
return NULL;
int mid = left + ((right - left) / 2);
struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
root->val = nums[mid];
root->left = traversal(nums, left, mid - 1);
root->right = traversal(nums, mid + 1, right);
return root;
}
struct TreeNode* sortedArrayToBST(int* nums, int numsSize) {
struct TreeNode* root = traversal(nums, 0, numsSize - 1);
return root;
}
```
-----------------------
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)

View File

@ -635,6 +635,108 @@ var isBalanced = function(root) {
};
```
## C
递归法:
```c
int getDepth(struct TreeNode* node) {
//如果结点不存在返回0
if(!node)
return 0;
//求出右子树深度
int rightDepth = getDepth(node->right);
//求出左子树深度
int leftDepth = getDepth(node->left);
//返回左右子树中的较大值+1
return rightDepth > leftDepth ? rightDepth + 1 : leftDepth + 1;
}
bool isBalanced(struct TreeNode* root) {
//递归结束条件为传入结点为NULL返回True
if(!root)
return 1;
//求出左右子树的深度
int leftDepth = getDepth(root->left);
int rightDepth = getDepth(root->right);
int diff;
//若左右子树绝对值差距大于1返回False
if((diff = leftDepth - rightDepth) > 1 || diff < -1)
return 0;
//检查左右子树是否为平衡二叉树
return isBalanced(root->right) && isBalanced(root->left);
}
```
迭代法:
```c
//计算结点深度
int getDepth(struct TreeNode* node) {
//开辟栈空间
struct TreeNode** stack = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 10000);
int stackTop = 0;
//若传入结点存在将其入栈。若不存在函数直接返回0
if(node)
stack[stackTop++] = node;
int result = 0;
int depth = 0;
//当栈中有元素时,进行迭代遍历
while(stackTop) {
//取出栈顶元素
struct TreeNode* tempNode = stack[--stackTop];
//若栈顶元素非NULL则将深度+1
if(tempNode) {
depth++;
//将栈顶元素再次入栈添加NULL表示此结点已被遍历
stack[stackTop++] = tempNode;
stack[stackTop++] = NULL;
//若栈顶元素有左右孩子,则将孩子结点入栈
if(tempNode->left)
stack[stackTop++] = tempNode->left;
if(tempNode->right)
stack[stackTop++] = tempNode->right;
//更新结果
result = result > depth ? result : depth;
}
else {
//若为NULL则代表当前结点已被遍历深度-1
tempNode = stack[--stackTop];
depth--;
}
}
return result;
}
bool isBalanced(struct TreeNode* root){
//开辟栈空间
struct TreeNode** stack = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 10000);
int stackTop = 0;
//若根节点不存在返回True
if(!root)
return 1;
//将根节点入栈
stack[stackTop++] = root;
//当栈中有元素时,进行遍历
while(stackTop) {
//将栈顶元素出栈
struct TreeNode* node = stack[--stackTop];
//计算左右子树的深度
int diff = getDepth(node->right) - getDepth(node->left);
//若深度的绝对值大于1返回False
if(diff > 1 || diff < -1)
return 0;
//如果栈顶结点有左右结点,将左右结点入栈
if(node->left)
stack[stackTop++] = node->left;
if(node->right)
stack[stackTop++] = node->right;
}
//若二叉树遍历结束后没有返回False则返回True
return 1;
}
```
-----------------------
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)

View File

@ -154,7 +154,7 @@ class Solution { // 动态规划
// [天数][是否持有股票]
int[][] dp = new int[prices.length][2];
// bad case
// base case
dp[0][0] = 0;
dp[0][1] = -prices[0];

View File

@ -200,6 +200,31 @@ class Solution:
Go
```go
func maxProfit(prices []int) int {
//创建数组
dp:=make([][]int,len(prices))
for i:=0;i<len(prices);i++{
dp[i]=make([]int,2)
}
dp[0][0]=-prices[0]
dp[0][1]=0
for i:=1;i<len(prices);i++{
dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i])
dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i])
}
return dp[len(prices)-1][1]
}
func max(a,b int)int{
if a<b{
return b
}
return a
}
```
Javascript
```javascript
// 方法一动态规划dp 数组)

View File

@ -278,6 +278,38 @@ class Solution:
return dp[4]
```
Go:
```go
func maxProfit(prices []int) int {
dp:=make([][]int,len(prices))
for i:=0;i<len(prices);i++{
dp[i]=make([]int,5)
}
dp[0][0]=0
dp[0][1]=-prices[0]
dp[0][2]=0
dp[0][3]=-prices[0]
dp[0][4]=0
for i:=1;i<len(prices);i++{
dp[i][0]=dp[i-1][0]
dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i])
dp[i][2]=max(dp[i-1][2],dp[i-1][1]+prices[i])
dp[i][3]=max(dp[i-1][3],dp[i-1][2]-prices[i])
dp[i][4]=max(dp[i-1][4],dp[i-1][3]+prices[i])
}
return dp[len(prices)-1][4]
}
func max(a,b int)int{
if a>b{
return a
}
return b
}
```
JavaScript
> 版本一:

View File

@ -300,6 +300,94 @@ class Solution {
}
```
```java
//解法二创建新字符数组填充。时间复杂度O(n)
class Solution {
public String reverseWords(String s) {
//源字符数组
char[] initialArr = s.toCharArray();
//新字符数组
char[] newArr = new char[initialArr.length+1];//下面循环添加"单词 ",最终末尾的空格不会返回
int newArrPos = 0;
//i来进行整体对源字符数组从后往前遍历
int i = initialArr.length-1;
while(i>=0){
while(i>=0 && initialArr[i] == ' '){i--;} //跳过空格
//此时i位置是边界或!=空格先记录当前索引之后的while用来确定单词的首字母的位置
int right = i;
while(i>=0 && initialArr[i] != ' '){i--;}
//指定区间单词取出(由于i为首字母的前一位所以这里+1,),取出的每组末尾都带有一个空格
for (int j = i+1; j <= right; j++) {
newArr[newArrPos++] = initialArr[j];
if(j == right){
newArr[newArrPos++] = ' ';//空格
}
}
}
//若是原始字符串没有单词直接返回空字符串若是有单词返回0-末尾空格索引前范围的字符数组(转成String返回)
if(newArrPos == 0){
return "";
}else{
return new String(newArr,0,newArrPos-1);
}
}
}
```
```java
//解法三:双反转+移位在原始数组上进行反转。空间复杂度O(1)
class Solution {
/**
* 思路:
* ①反转字符串 "the sky is blue " => " eulb si yks eht"
* ②遍历 " eulb si yks eht",每次先对某个单词进行反转再移位
* 这里以第一个单词进行为演示:" eulb si yks eht" ==反转=> " blue si yks eht" ==移位=> "blue si yks eht"
*/
public String reverseWords(String s) {
//步骤1字符串整体反转此时其中的单词也都反转了
char[] initialArr = s.toCharArray();
reverse(initialArr, 0, s.length() - 1);
int k = 0;
for (int i = 0; i < initialArr.length; i++) {
if (initialArr[i] == ' ') {
continue;
}
int tempCur = i;
while (i < initialArr.length && initialArr[i] != ' ') {
i++;
}
for (int j = tempCur; j < i; j++) {
if (j == tempCur) { //步骤二:二次反转
reverse(initialArr, tempCur, i - 1);//对指定范围字符串进行反转,不反转从后往前遍历一个个填充有问题
}
//步骤三:移动操作
initialArr[k++] = initialArr[j];
if (j == i - 1) { //遍历结束
//避免越界情况,例如=> "asdasd df f",不加判断最后就会数组越界
if (k < initialArr.length) {
initialArr[k++] = ' ';
}
}
}
}
if (k == 0) {
return "";
} else {
//参数三:以防出现如"asdasd df f"=>"f df asdasd"正好凑满不需要省略空格情况
return new String(initialArr, 0, (k == initialArr.length) && (initialArr[k - 1] != ' ') ? k : k - 1);
}
}
public void reverse(char[] chars, int begin, int end) {
for (int i = begin, j = end; i < j; i++, j--) {
chars[i] ^= chars[j];
chars[j] ^= chars[i];
chars[i] ^= chars[j];
}
}
}
```
python:
```Python

View File

@ -276,6 +276,42 @@ class Solution:
```
Go
```go
func maxProfit(k int, prices []int) int {
if len(prices)==0{
return 0
}
dp:=make([][]int,len(prices))
for i:=0;i<len(prices);i++{
dp[i]=make([]int,2*k+1)
}
for i:=1;i<len(dp[0]);i++{
if i%2!=0{
dp[0][i]=-prices[0]
}
}
for i:=1;i<len(prices);i++{
dp[i][0]=dp[i-1][0]
for j:=1;j<len(dp[0]);j++{
if j%2!=0{
dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]-prices[i])
}else {
dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+prices[i])
}
}
}
return dp[len(prices)-1][2*k]
}
func max(a,b int)int{
if a>b{
return a
}
return b
}
```
Javascript

View File

@ -215,6 +215,23 @@ var isHappy = function(n) {
}
return n === 1;
};
// 方法四使用Set()求和用reduce
var isHappy = function(n) {
let set = new Set();
let totalCount;
while(totalCount !== 1) {
let arr = (''+(totalCount || n)).split('');
totalCount = arr.reduce((total, num) => {
return total + num * num
}, 0)
if (set.has(totalCount)) {
return false;
}
set.add(totalCount);
}
return true;
};
```
Swift

View File

@ -358,6 +358,41 @@ func removeElements(head *ListNode, val int) *ListNode {
}
```
RUST:
```rust
// Definition for singly-linked list.
// #[derive(PartialEq, Eq, Clone, Debug)]
// pub struct ListNode {
// pub val: i32,
// pub next: Option<Box<ListNode>>
// }
//
// impl ListNode {
// #[inline]
// fn new(val: i32) -> Self {
// ListNode {
// next: None,
// val
// }
// }
// }
impl Solution {
pub fn remove_elements(head: Option<Box<ListNode>>, val: i32) -> Option<Box<ListNode>> {
let mut head = head;
let mut dummy_head = ListNode::new(0);
let mut cur = &mut dummy_head;
while let Some(mut node) = head {
head = std::mem::replace(&mut node.next, None);
if node.val != val {
cur.next = Some(node);
cur = cur.next.as_mut().unwrap();
}
}
dummy_head.next
}
}
```
-----------------------
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
* B站视频[代码随想录](https://space.bilibili.com/525438321)

View File

@ -166,7 +166,41 @@ const robRange = (nums, start, end) => {
}
```
Go
```go
// 打家劫舍Ⅱ 动态规划
// 时间复杂度O(n) 空间复杂度O(n)
func rob(nums []int) int {
if len(nums) == 1 {
return nums[0]
}
if len(nums) == 2 {
return max(nums[0], nums[1])
}
result1 := robRange(nums, 0)
result2 := robRange(nums, 1)
return max(result1, result2)
}
// 偷盗指定的范围
func robRange(nums []int, start int) int {
dp := make([]int, len(nums))
dp[1] = nums[start]
for i := 2; i < len(nums); i++ {
dp[i] = max(dp[i - 2] + nums[i - 1 + start], dp[i - 1])
}
return dp[len(nums) - 1]
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
```

View File

@ -359,6 +359,72 @@ class MyStack:
Go
使用两个队列实现
```go
type MyStack struct {
//创建两个队列
queue1 []int
queue2 []int
}
func Constructor() MyStack {
return MyStack{ //初始化
queue1:make([]int,0),
queue2:make([]int,0),
}
}
func (this *MyStack) Push(x int) {
//先将数据存在queue2中
this.queue2 = append(this.queue2,x)
//将queue1中所有元素移到queue2中再将两个队列进行交换
this.Move()
}
func (this *MyStack) Move(){
if len(this.queue1) == 0{
//交换queue1置为queue2,queue2置为空
this.queue1,this.queue2 = this.queue2,this.queue1
}else{
//queue1元素从头开始一个一个追加到queue2中
this.queue2 = append(this.queue2,this.queue1[0])
this.queue1 = this.queue1[1:] //去除第一个元素
this.Move() //重复
}
}
func (this *MyStack) Pop() int {
val := this.queue1[0]
this.queue1 = this.queue1[1:] //去除第一个元素
return val
}
func (this *MyStack) Top() int {
return this.queue1[0] //直接返回
}
func (this *MyStack) Empty() bool {
return len(this.queue1) == 0
}
/**
* Your MyStack object will be instantiated and called as such:
* obj := Constructor();
* obj.Push(x);
* param_2 := obj.Pop();
* param_3 := obj.Top();
* param_4 := obj.Empty();
*/
```
使用一个队列实现
```go
type MyStack struct {
queue []int//创建一个队列

View File

@ -469,6 +469,9 @@ class Solution:
---
Go
递归法:
```go
func binaryTreePaths(root *TreeNode) []string {
res := make([]string, 0)
@ -491,10 +494,45 @@ func binaryTreePaths(root *TreeNode) []string {
return res
}
```
迭代法:
```go
func binaryTreePaths(root *TreeNode) []string {
stack := []*TreeNode{}
paths := make([]string, 0)
res := make([]string, 0)
if root != nil {
stack = append(stack, root)
paths = append(paths, "")
}
for len(stack) > 0 {
l := len(stack)
node := stack[l-1]
path := paths[l-1]
stack = stack[:l-1]
paths = paths[:l-1]
if node.Left == nil && node.Right == nil {
res = append(res, path+strconv.Itoa(node.Val))
continue
}
if node.Right != nil {
stack = append(stack, node.Right)
paths = append(paths, path+strconv.Itoa(node.Val)+"->")
}
if node.Left != nil {
stack = append(stack, node.Left)
paths = append(paths, path+strconv.Itoa(node.Val)+"->")
}
}
return res
}
```
---
JavaScript:
1.递归版本
递归法:
```javascript
var binaryTreePaths = function(root) {
@ -518,6 +556,32 @@ var binaryTreePaths = function(root) {
};
```
迭代法:
```javascript
var binaryTreePaths = function(root) {
if (!root) return [];
const stack = [root], paths = [''], res = [];
while (stack.length) {
const node = stack.pop();
let path = paths.pop();
if (!node.left && !node.right) { // 到叶子节点终止, 添加路径到结果中
res.push(path + node.val);
continue;
}
path += node.val + '->';
if (node.right) { // 右节点存在
stack.push(node.right);
paths.push(path);
}
if (node.left) { // 左节点存在
stack.push(node.left);
paths.push(path);
}
}
return res;
};
```

View File

@ -430,6 +430,35 @@ const rob = root => {
};
```
Go:
```go
// 打家劫舍Ⅲ 动态规划
// 时间复杂度O(n) 空间复杂度O(logn)
func rob(root *TreeNode) int {
dp := traversal(root)
return max(dp[0], dp[1])
}
func traversal(cur *TreeNode) []int {
if cur == nil {
return []int{0, 0}
}
dpL := traversal(cur.Left)
dpR := traversal(cur.Right)
val1 := cur.Val + dpL[0] + dpR[0] // 偷盗当前节点
val2 := max(dpL[0], dpL[1]) + max(dpR[0], dpR[1]) // 不偷盗当前节点
return []int{val2, val1}
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
```

View File

@ -198,8 +198,38 @@ class Solution {
}
}
```
```java
// DP
class Solution {
public int wiggleMaxLength(int[] nums) {
// 0 i 作为波峰的最大长度
// 1 i 作为波谷的最大长度
int dp[][] = new int[nums.length][2];
dp[0][0] = dp[0][1] = 1;
for (int i = 1; i < nums.length; i++){
//i 自己可以成为波峰或者波谷
dp[i][0] = dp[i][1] = 1;
for (int j = 0; j < i; j++){
if (nums[j] > nums[i]){
// i 是波谷
dp[i][1] = Math.max(dp[i][1], dp[j][0] + 1);
}
if (nums[j] < nums[i]){
// i 是波峰
dp[i][0] = Math.max(dp[i][0], dp[j][1] + 1);
}
}
}
return Math.max(dp[nums.length - 1][0], dp[nums.length - 1][1]);
}
}
```
### Python
```python3
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:

View File

@ -485,6 +485,41 @@ var deleteNode = function (root, key) {
};
```
迭代
``` javascript
var deleteNode = function (root, key) {
const deleteOneNode = target => {
if (!target) return target
if (!target.right) return target.left
let cur = target.right
while (cur.left) {
cur = cur.left
}
cur.left = target.left
return target.right
}
if (!root) return root
let cur = root
let pre = null
while (cur) {
if (cur.val === key) break
pre = cur
cur.val > key ? cur = cur.left : cur = cur.right
}
if (!pre) {
return deleteOneNode(cur)
}
if (pre.left && pre.left.val === key) {
pre.left = deleteOneNode(cur)
}
if (pre.right && pre.right.val === key) {
pre.right = deleteOneNode(cur)
}
return root
}
```
-----------------------

View File

@ -186,6 +186,26 @@ class Solution {
}
```
```java
//非压缩状态的版本
class Solution {
public int fib(int n) {
if (n <= 1) return n;
int[] dp = new int[n + 1];
dp[0] = 0;
dp[1] = 1;
for (int index = 2; index <= n; index++){
dp[index] = dp[index - 1] + dp[index - 2];
}
return dp[n];
}
}
```
Python
```python3
class Solution:

View File

@ -293,6 +293,27 @@ var convertBST = function (root) {
};
```
##C
递归
```c
int pre;
void traversal(struct TreeNode* node) {
if(!node)
return ;
traversal(node->right);
node->val = node->val + pre;
pre = node->val;
traversal(node->left);
}
struct TreeNode* convertBST(struct TreeNode* root){
pre = 0;
traversal(root);
return root;
}
```
-----------------------
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
* B站视频[代码随想录](https://space.bilibili.com/525438321)

View File

@ -331,6 +331,59 @@ func commonChars(_ words: [String]) -> [String] {
}
```
C:
```c
//若两个哈希表定义为char数组每个单词的最大长度不会超过100因此可以用char表示可以提高时间和空间效率
void updateHashTable(int* hashTableOne, int* hashTableTwo) {
int i;
for(i = 0; i < 26; i++) {
hashTableOne[i] = hashTableOne[i] < hashTableTwo[i] ? hashTableOne[i] : hashTableTwo[i];
}
}
char ** commonChars(char ** words, int wordsSize, int* returnSize){
//用来统计所有字母出现的最小频率
int hashTable[26] = { 0 };
//初始化返回的char**数组以及返回数组长度
*returnSize = 0;
char** ret = (char**)malloc(sizeof(char*) * 100);
//如果输入数组长度为0则返回NULL
if(!wordsSize)
return NULL;
int i;
//更新第一个单词的字母频率
for(i = 0; i < strlen(words[0]); i++)
hashTable[words[0][i] - 'a']++;
//更新从第二个单词开始的字母频率
for(i = 1; i < wordsSize; i++) {
//创建新的哈希表,记录新的单词的字母频率
int newHashTable[26] = { 0 };
int j;
for(j = 0; j < strlen(words[i]); j++) {
newHashTable[words[i][j] - 'a']++;
}
//更新原哈希表
updateHashTable(hashTable, newHashTable);
}
//将哈希表中的字符变为字符串放入ret中
for(i = 0; i < 26; i++) {
if(hashTable[i]) {
int j;
for(j = 0; j < hashTable[i]; j++) {
char* tempString = (char*)malloc(sizeof(char) * 2);
tempString[0] = i + 'a';
tempString[1] = '\0';
ret[(*returnSize)++] = tempString;
}
}
}
return ret;
}
```
-----------------------
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
* B站视频[代码随想录](https://space.bilibili.com/525438321)

View File

@ -299,108 +299,96 @@ class Solution:
Go
> 迭代法前序遍历
```go
//迭代法前序遍历
/**
type Element struct {
// 元素保管的值
Value interface{}
// 内含隐藏或非导出字段
}
func (l *List) Back() *Element
前序遍历:中左右
压栈顺序:右左中
**/
func preorderTraversal(root *TreeNode) []int {
ans := []int{}
if root == nil {
return nil
return ans
}
var stack = list.New()
stack.PushBack(root.Right)
stack.PushBack(root.Left)
res:=[]int{}
res=append(res,root.Val)
for stack.Len()>0 {
e:=stack.Back()
stack.Remove(e)
node := e.Value.(*TreeNode)//e是Element类型其值为e.Value.由于Value为接口所以要断言
if node==nil{
continue
st := list.New()
st.PushBack(root)
for st.Len() > 0 {
node := st.Remove(st.Back()).(*TreeNode)
ans = append(ans, node.Val)
if node.Right != nil {
st.PushBack(node.Right)
}
if node.Left != nil {
st.PushBack(node.Left)
}
res=append(res,node.Val)
stack.PushBack(node.Right)
stack.PushBack(node.Left)
}
return res
return ans
}
```
> 迭代法后序遍历
```go
//迭代法后序遍历
//后续遍历:左右中
//压栈顺序:中右左(按照前序遍历思路),再反转结果数组
func postorderTraversal(root *TreeNode) []int {
ans := []int{}
if root == nil {
return nil
return ans
}
var stack = list.New()
stack.PushBack(root.Left)
stack.PushBack(root.Right)
res:=[]int{}
res=append(res,root.Val)
for stack.Len()>0 {
e:=stack.Back()
stack.Remove(e)
node := e.Value.(*TreeNode)//e是Element类型其值为e.Value.由于Value为接口所以要断言
if node==nil{
continue
st := list.New()
st.PushBack(root)
for st.Len() > 0 {
node := st.Remove(st.Back()).(*TreeNode)
ans = append(ans, node.Val)
if node.Left != nil {
st.PushBack(node.Left)
}
if node.Right != nil {
st.PushBack(node.Right)
}
res=append(res,node.Val)
stack.PushBack(node.Left)
stack.PushBack(node.Right)
}
for i:=0;i<len(res)/2;i++{
res[i],res[len(res)-i-1] = res[len(res)-i-1],res[i]
reverse(ans)
return ans
}
func reverse(a []int) {
l, r := 0, len(a) - 1
for l < r {
a[l], a[r] = a[r], a[l]
l, r = l+1, r-1
}
return res
}
```
> 迭代法中序遍历
```go
//迭代法中序遍历
func inorderTraversal(root *TreeNode) []int {
rootRes:=[]int{}
if root==nil{
return nil
ans := []int{}
if root == nil {
return ans
}
stack:=list.New()
node:=root
//先将所有左节点找到,加入栈中
for node!=nil{
stack.PushBack(node)
node=node.Left
}
//其次对栈中的每个节点先弹出加入到结果集中,再找到该节点的右节点的所有左节点加入栈中
for stack.Len()>0{
e:=stack.Back()
node:=e.Value.(*TreeNode)
stack.Remove(e)
//找到该节点的右节点,再搜索他的所有左节点加入栈中
rootRes=append(rootRes,node.Val)
node=node.Right
for node!=nil{
stack.PushBack(node)
node=node.Left
st := list.New()
cur := root
for cur != nil || st.Len() > 0 {
if cur != nil {
st.PushBack(cur)
cur = cur.Left
} else {
cur = st.Remove(st.Back()).(*TreeNode)
ans = append(ans, cur.Val)
cur = cur.Right
}
}
return rootRes
return ans
}
```

View File

@ -54,7 +54,7 @@ traversal(cur->left, vec); // 左
traversal(cur->right, vec); // 右
```
单层递归的逻辑就是按照中左右的顺序来处理的,这样二叉树的前序遍历,基本就写完了,看一下完整代码:
单层递归的逻辑就是按照中左右的顺序来处理的,这样二叉树的前序遍历,基本就写完了,看一下完整代码:
前序遍历:

View File

@ -144,6 +144,41 @@ public static String replaceSpace(StringBuffer str) {
}
return sb.toString();
}
//方式二:双指针法
public String replaceSpace(String s) {
if(s == null || s.length() == 0){
return s;
}
//扩充空间空格数量2倍
StringBuilder str = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if(s.charAt(i) == ' '){
str.append(" ");
}
}
//若是没有空格直接返回
if(str.length() == 0){
return s;
}
//有空格情况 定义两个指针
int left = s.length() - 1;//左指针:指向原始字符串最后一个位置
s += str.toString();
int right = s.length()-1;//右指针:指向扩展字符串的最后一个位置
char[] chars = s.toCharArray();
while(left>=0){
if(chars[left] == ' '){
chars[right--] = '0';
chars[right--] = '2';
chars[right] = '%';
}else{
chars[right] = chars[left];
}
left--;
right--;
}
return new String(chars);
}
```

View File

@ -6,7 +6,7 @@
在[贪心算法:用最少数量的箭引爆气球](https://programmercarl.com/0452.用最少数量的箭引爆气球.html)中,我们开始讲解了重叠区间问题,用最少的弓箭射爆所有气球,其本质就是找到最大的重叠区间。
按照左边界行排序后,如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭
按照左边界行排序后,如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭
如图:
@ -28,7 +28,7 @@
弓箭的数量就相当于是非交叉区间的数量,只要把弓箭那道题目代码里射爆气球的判断条件加个等号(认为[01][12]不是相邻区间),然后用总区间数减去弓箭数量 就是要移除的区间数量了。
把[贪心算法:用最少数量的箭引爆气球](https://programmercarl.com/0452.用最少数量的箭引爆气球.html)代码稍做修改,可以AC本题。
把[贪心算法:用最少数量的箭引爆气球](https://programmercarl.com/0452.用最少数量的箭引爆气球.html)代码稍做修改,可以AC本题。
修改后的C++代码如下:
```CPP
@ -60,7 +60,7 @@ public:
[贪心算法:划分字母区间](https://programmercarl.com/0763.划分字母区间.html)中我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。
这道题目leetcode上标的是贪心其实我不认是贪心,因为没感受到局部最优和全局最优的关系。
这道题目leetcode上标的是贪心其实我不认是贪心,因为没感受到局部最优和全局最优的关系。
但不影响这是一道好题,思路很不错,**通过字符出现最远距离取并集的方法,把出现过的字符都圈到一个区间里**。
@ -91,7 +91,7 @@ public:
## 总结
本周的主题就是用贪心算法来解决区间问题过本周的学习大家应该对区间的各种合并分割有一定程度的了解了
本周的主题就是用贪心算法来解决区间问题过本周的学习大家应该对区间的各种合并分割有一定程度的了解了
其实很多区间的合并操作看起来都是常识其实贪心算法有时候就是常识哈哈但也别小看了贪心算法

View File

@ -32,7 +32,7 @@
## 哈希函数
哈希函数,把学生的姓名直接映射为哈希表上的索引,然后就可以通过查询索引下快速知道这位同学是否在这所学校里了。
哈希函数,把学生的姓名直接映射为哈希表上的索引,然后就可以通过查询索引下快速知道这位同学是否在这所学校里了。
哈希函数如下图所示通过hashCode把名字转化为数值一般hashcode是通过特定编码方式可以将其他数据格式转化为不同的数值这样就把学生名字映射为哈希表上的索引数字了。

View File

@ -249,6 +249,45 @@ used数组可是全局变量每层与每层之间公用一个used数组
Java
**47.全排列II**
```java
class Solution {
private List<List<Integer>> res = new ArrayList<>();
private List<Integer> path = new ArrayList<>();
private boolean[] used = null;
public List<List<Integer>> permuteUnique(int[] nums) {
used = new boolean[nums.length];
Arrays.sort(nums);
backtracking(nums);
return res;
}
public void backtracking(int[] nums) {
if (path.size() == nums.length) {
res.add(new ArrayList<>(path));
return;
}
HashSet<Integer> hashSet = new HashSet<>();//层去重
for (int i = 0; i < nums.length; i++) {
if (hashSet.contains(nums[i]))
continue;
if (used[i] == true)//枝去重
continue;
hashSet.add(nums[i]);//记录元素
used[i] = true;
path.add(nums[i]);
backtracking(nums);
path.remove(path.size() - 1);
used[i] = false;
}
}
}
```
Python

View File

@ -38,7 +38,7 @@
![面试题02.07.链表相交_2](https://code-thinking.cdn.bcebos.com/pics/面试题02.07.链表相交_2.png)
此时我们就可以比较curA和curB是否相同如果不相同同时向后移动curA和curB如果遇到curA == curB则找到点。
此时我们就可以比较curA和curB是否相同如果不相同同时向后移动curA和curB如果遇到curA == curB则找到点。
否则循环退出返回空指针。