mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-12 13:45:39 +08:00
Update
This commit is contained in:
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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]);
|
||||
|
@ -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 {
|
||||
/**
|
||||
|
@ -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;
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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 数组)
|
||||
|
@ -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:
|
||||
|
||||
> 版本一:
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -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//创建一个队列
|
||||
|
@ -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;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -54,7 +54,7 @@ traversal(cur->left, vec); // 左
|
||||
traversal(cur->right, vec); // 右
|
||||
```
|
||||
|
||||
单层递归的逻辑就是按照中左右的顺序来处理的,这样二叉树的前序遍历,基本就写完了,在看一下完整代码:
|
||||
单层递归的逻辑就是按照中左右的顺序来处理的,这样二叉树的前序遍历,基本就写完了,再看一下完整代码:
|
||||
|
||||
前序遍历:
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
在[贪心算法:用最少数量的箭引爆气球](https://programmercarl.com/0452.用最少数量的箭引爆气球.html)中,我们开始讲解了重叠区间问题,用最少的弓箭射爆所有气球,其本质就是找到最大的重叠区间。
|
||||
|
||||
按照左边界经行排序后,如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭
|
||||
按照左边界进行排序后,如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭
|
||||
|
||||
如图:
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
|
||||
弓箭的数量就相当于是非交叉区间的数量,只要把弓箭那道题目代码里射爆气球的判断条件加个等号(认为[0,1][1,2]不是相邻区间),然后用总区间数减去弓箭数量 就是要移除的区间数量了。
|
||||
|
||||
把[贪心算法:用最少数量的箭引爆气球](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:
|
||||
|
||||
## 总结
|
||||
|
||||
本周的主题就是用贪心算法来解决区间问题,进过本周的学习,大家应该对区间的各种合并分割有一定程度的了解了。
|
||||
本周的主题就是用贪心算法来解决区间问题,经过本周的学习,大家应该对区间的各种合并分割有一定程度的了解了。
|
||||
|
||||
其实很多区间的合并操作看起来都是常识,其实贪心算法有时候就是常识,哈哈,但也别小看了贪心算法。
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
## 哈希函数
|
||||
|
||||
哈希函数,把学生的姓名直接映射为哈希表上的索引,然后就可以通过查询索引下表快速知道这位同学是否在这所学校里了。
|
||||
哈希函数,把学生的姓名直接映射为哈希表上的索引,然后就可以通过查询索引下标快速知道这位同学是否在这所学校里了。
|
||||
|
||||
哈希函数如下图所示,通过hashCode把名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把学生名字映射为哈希表上的索引数字了。
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||

|
||||
|
||||
此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到焦点。
|
||||
此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
|
||||
|
||||
否则循环退出返回空指针。
|
||||
|
||||
|
Reference in New Issue
Block a user