mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-09 19:44:45 +08:00
Merge branch 'youngyangyang04:master' into master
This commit is contained in:
@ -337,5 +337,48 @@ object Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
PHP:
|
||||||
|
```php
|
||||||
|
//虚拟头结点
|
||||||
|
function swapPairs($head) {
|
||||||
|
if ($head == null || $head->next == null) {
|
||||||
|
return $head;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dummyNode = new ListNode(0, $head);
|
||||||
|
$preNode = $dummyNode; //虚拟头结点
|
||||||
|
$curNode = $head;
|
||||||
|
$nextNode = $head->next;
|
||||||
|
while($curNode && $nextNode) {
|
||||||
|
$nextNextNode = $nextNode->next; //存下一个节点
|
||||||
|
$nextNode->next = $curNode; //交换curHead 和 nextHead
|
||||||
|
$curNode->next = $nextNextNode;
|
||||||
|
$preNode->next = $nextNode; //上一个节点的下一个指向指向nextHead
|
||||||
|
|
||||||
|
//更新当前的几个指针
|
||||||
|
$preNode = $preNode->next->next;
|
||||||
|
$curNode = $nextNextNode;
|
||||||
|
$nextNode = $nextNextNode->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dummyNode->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
//递归版本
|
||||||
|
function swapPairs($head)
|
||||||
|
{
|
||||||
|
// 终止条件
|
||||||
|
if ($head === null || $head->next === null) {
|
||||||
|
return $head;
|
||||||
|
}
|
||||||
|
|
||||||
|
//结果要返回的头结点
|
||||||
|
$next = $head->next;
|
||||||
|
$head->next = $this->swapPairs($next->next); //当前头结点->next指向更新
|
||||||
|
$next->next = $head; //当前第二个节点的->next指向更新
|
||||||
|
return $next; //返回翻转后的头结点
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||||
|
@ -154,10 +154,6 @@ public:
|
|||||||
* 844.比较含退格的字符串
|
* 844.比较含退格的字符串
|
||||||
* 977.有序数组的平方
|
* 977.有序数组的平方
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 其他语言版本
|
## 其他语言版本
|
||||||
|
|
||||||
|
|
||||||
@ -165,18 +161,35 @@ Java:
|
|||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
public int removeElement(int[] nums, int val) {
|
public int removeElement(int[] nums, int val) {
|
||||||
|
|
||||||
// 快慢指针
|
// 快慢指针
|
||||||
int fastIndex = 0;
|
int slowIndex = 0;
|
||||||
int slowIndex;
|
for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
|
||||||
for (slowIndex = 0; fastIndex < nums.length; fastIndex++) {
|
|
||||||
if (nums[fastIndex] != val) {
|
if (nums[fastIndex] != val) {
|
||||||
nums[slowIndex] = nums[fastIndex];
|
nums[slowIndex] = nums[fastIndex];
|
||||||
slowIndex++;
|
slowIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return slowIndex;
|
return slowIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
```java
|
||||||
|
//相向双指针法
|
||||||
|
class Solution {
|
||||||
|
public int removeElement(int[] nums, int val) {
|
||||||
|
int left = 0;
|
||||||
|
int right = nums.length - 1;
|
||||||
|
while(right >= 0 && nums[right] == val) right--; //将right移到从右数第一个值不为val的位置
|
||||||
|
while(left <= right) {
|
||||||
|
if(nums[left] == val) { //left位置的元素需要移除
|
||||||
|
//将right位置的元素移到left(覆盖),right位置移除
|
||||||
|
nums[left] = nums[right];
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
left++;
|
||||||
|
while(right >= 0 && nums[right] == val) right--;
|
||||||
|
}
|
||||||
|
return left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -226,7 +226,32 @@ class Solution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
```java
|
||||||
|
//第二种二分法:左闭右开
|
||||||
|
public int searchInsert(int[] nums, int target) {
|
||||||
|
int left = 0;
|
||||||
|
int right = nums.length;
|
||||||
|
while (left < right) { //左闭右开 [left, right)
|
||||||
|
int middle = left + ((right - left) >> 1);
|
||||||
|
if (nums[middle] > target) {
|
||||||
|
right = middle; // target 在左区间,在[left, middle)中
|
||||||
|
} else if (nums[middle] < target) {
|
||||||
|
left = middle + 1; // target 在右区间,在 [middle+1, right)中
|
||||||
|
} else { // nums[middle] == target
|
||||||
|
return middle; // 数组中找到目标值的情况,直接返回下标
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 目标值在数组所有元素之前 [0,0)
|
||||||
|
// 目标值插入数组中的位置 [left, right) ,return right 即可
|
||||||
|
// 目标值在数组所有元素之后的情况 [left, right),因为是右开区间,所以 return right
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Golang:
|
Golang:
|
||||||
|
|
||||||
```golang
|
```golang
|
||||||
// 第一种二分法
|
// 第一种二分法
|
||||||
func searchInsert(nums []int, target int) int {
|
func searchInsert(nums []int, target int) int {
|
||||||
|
@ -114,7 +114,7 @@ vector<vector<int>> result; // 存放符合条件结果的集合
|
|||||||
vector<int> path; // 用来存放符合条件结果
|
vector<int> path; // 用来存放符合条件结果
|
||||||
```
|
```
|
||||||
|
|
||||||
其实不定义这两个全局遍历也是可以的,把这两个变量放进递归函数的参数里,但函数里参数太多影响可读性,所以我定义全局变量了。
|
其实不定义这两个全局变量也是可以的,把这两个变量放进递归函数的参数里,但函数里参数太多影响可读性,所以我定义全局变量了。
|
||||||
|
|
||||||
函数里一定有两个参数,既然是集合n里面取k的数,那么n和k是两个int型的参数。
|
函数里一定有两个参数,既然是集合n里面取k的数,那么n和k是两个int型的参数。
|
||||||
|
|
||||||
|
@ -252,6 +252,24 @@ function numTrees(n: number): number {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Rust
|
||||||
|
|
||||||
|
```Rust
|
||||||
|
impl Solution {
|
||||||
|
pub fn num_trees(n: i32) -> i32 {
|
||||||
|
let n = n as usize;
|
||||||
|
let mut dp = vec![0; n + 1];
|
||||||
|
dp[0] = 1;
|
||||||
|
for i in 1..=n {
|
||||||
|
for j in 1..=i {
|
||||||
|
dp[i] += dp[j - 1] * dp[i - j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dp[n]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### C
|
### C
|
||||||
|
|
||||||
```c
|
```c
|
||||||
|
@ -206,6 +206,65 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
```
|
||||||
|
# 优化
|
||||||
|
|
||||||
|
上面的代码还存在一定的优化空间, 在于如何更高效的计算一个子字符串是否是回文字串。上述代码```isPalindrome```函数运用双指针的方法来判定对于一个字符串```s```, 给定起始下标和终止下标, 截取出的子字符串是否是回文字串。但是其中有一定的重复计算存在:
|
||||||
|
|
||||||
|
例如给定字符串```"abcde"```, 在已知```"bcd"```不是回文字串时, 不再需要去双指针操作```"abcde"```而可以直接判定它一定不是回文字串。
|
||||||
|
|
||||||
|
具体来说, 给定一个字符串`s`, 长度为```n```, 它成为回文字串的充分必要条件是```s[0] == s[n-1]```且```s[1:n-1]```是回文字串。
|
||||||
|
|
||||||
|
大家如果熟悉动态规划这种算法的话, 我们可以高效地事先一次性计算出, 针对一个字符串```s```, 它的任何子串是否是回文字串, 然后在我们的回溯函数中直接查询即可, 省去了双指针移动判定这一步骤.
|
||||||
|
|
||||||
|
具体参考代码如下:
|
||||||
|
|
||||||
|
```CPP
|
||||||
|
class Solution {
|
||||||
|
private:
|
||||||
|
vector<vector<string>> result;
|
||||||
|
vector<string> path; // 放已经回文的子串
|
||||||
|
vector<vector<bool>> isPalindrome; // 放事先计算好的是否回文子串的结果
|
||||||
|
void backtracking (const string& s, int startIndex) {
|
||||||
|
// 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了
|
||||||
|
if (startIndex >= s.size()) {
|
||||||
|
result.push_back(path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = startIndex; i < s.size(); i++) {
|
||||||
|
if (isPalindrome[startIndex][i]) { // 是回文子串
|
||||||
|
// 获取[startIndex,i]在s中的子串
|
||||||
|
string str = s.substr(startIndex, i - startIndex + 1);
|
||||||
|
path.push_back(str);
|
||||||
|
} else { // 不是回文,跳过
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
backtracking(s, i + 1); // 寻找i+1为起始位置的子串
|
||||||
|
path.pop_back(); // 回溯过程,弹出本次已经填在的子串
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void computePalindrome(const string& s) {
|
||||||
|
// isPalindrome[i][j] 代表 s[i:j](双边包括)是否是回文字串
|
||||||
|
isPalindrome.resize(s.size(), vector<bool>(s.size(), false)); // 根据字符串s, 刷新布尔矩阵的大小
|
||||||
|
for (int i = s.size() - 1; i >= 0; i--) {
|
||||||
|
// 需要倒序计算, 保证在i行时, i+1行已经计算好了
|
||||||
|
for (int j = i; j < s.size(); j++) {
|
||||||
|
if (j == i) {isPalindrome[i][j] = true;}
|
||||||
|
else if (j - i == 1) {isPalindrome[i][j] = (s[i] == s[j]);}
|
||||||
|
else {isPalindrome[i][j] = (s[i] == s[j] && isPalindrome[i+1][j-1]);}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
vector<vector<string>> partition(string s) {
|
||||||
|
result.clear();
|
||||||
|
path.clear();
|
||||||
|
computePalindrome(s);
|
||||||
|
backtracking(s, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# 总结
|
# 总结
|
||||||
|
@ -65,6 +65,8 @@
|
|||||||
|
|
||||||
# 思路
|
# 思路
|
||||||
|
|
||||||
|
《代码随想录》算法视频公开课:[栈的最后表演! | LeetCode:150. 逆波兰表达式求值](https://www.bilibili.com/video/BV1kd4y1o7on),相信结合视频在看本篇题解,更有助于大家对本题的理解。
|
||||||
|
|
||||||
在上一篇文章中[1047.删除字符串中的所有相邻重复项](https://programmercarl.com/1047.删除字符串中的所有相邻重复项.html)提到了 递归就是用栈来实现的。
|
在上一篇文章中[1047.删除字符串中的所有相邻重复项](https://programmercarl.com/1047.删除字符串中的所有相邻重复项.html)提到了 递归就是用栈来实现的。
|
||||||
|
|
||||||
所以**栈与递归之间在某种程度上是可以转换的!** 这一点我们在后续讲解二叉树的时候,会更详细的讲解到。
|
所以**栈与递归之间在某种程度上是可以转换的!** 这一点我们在后续讲解二叉树的时候,会更详细的讲解到。
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
# 思路
|
# 思路
|
||||||
|
|
||||||
|
《代码随想录》算法视频公开课:[单调队列正式登场!| LeetCode:239. 滑动窗口最大值](https://www.bilibili.com/video/BV1XS4y1p7qj),相信结合视频在看本篇题解,更有助于大家对本题的理解。
|
||||||
|
|
||||||
这是使用单调队列的经典题目。
|
这是使用单调队列的经典题目。
|
||||||
|
|
||||||
难点是如何求一个区间里的最大值呢? (这好像是废话),暴力一下不就得了。
|
难点是如何求一个区间里的最大值呢? (这好像是废话),暴力一下不就得了。
|
||||||
|
@ -259,6 +259,21 @@ func max(a,b int) int{
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Rust
|
||||||
|
```rust
|
||||||
|
pub fn integer_break(n: i32) -> i32 {
|
||||||
|
let n = n as usize;
|
||||||
|
let mut dp = vec![0; n + 1];
|
||||||
|
dp[2] = 1;
|
||||||
|
for i in 3..=n {
|
||||||
|
for j in 1..i-1 {
|
||||||
|
dp[i] = dp[i].max((i - j) * j).max(dp[i - j] * j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dp[n] as i32
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Javascript
|
### Javascript
|
||||||
```Javascript
|
```Javascript
|
||||||
var integerBreak = function(n) {
|
var integerBreak = function(n) {
|
||||||
@ -299,6 +314,27 @@ function integerBreak(n: number): number {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Rust
|
||||||
|
|
||||||
|
```Rust
|
||||||
|
impl Solution {
|
||||||
|
fn max(a: i32, b: i32) -> i32{
|
||||||
|
if a > b { a } else { b }
|
||||||
|
}
|
||||||
|
pub fn integer_break(n: i32) -> i32 {
|
||||||
|
let n = n as usize;
|
||||||
|
let mut dp = vec![0; n + 1];
|
||||||
|
dp[2] = 1;
|
||||||
|
for i in 3..=n {
|
||||||
|
for j in 1..i - 1 {
|
||||||
|
dp[i] = Self::max(dp[i], Self::max(((i - j) * j) as i32, dp[i - j] * j as i32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dp[n]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### C
|
### C
|
||||||
|
|
||||||
```c
|
```c
|
||||||
|
@ -31,6 +31,14 @@
|
|||||||
|
|
||||||
# 思路
|
# 思路
|
||||||
|
|
||||||
|
《代码随想录》算法视频公开课:[优先级队列正式登场!大顶堆、小顶堆该怎么用?| LeetCode:347.前 K 个高频元素](https://www.bilibili.com/video/BV1Xg41167Lz),相信结合视频在看本篇题解,更有助于大家对本题的理解。
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<iframe src="//player.bilibili.com/player.html?aid=514643371&bvid=BV1Xg41167Lz&cid=808260290&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true" width=750 height=500> </iframe>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
这道题目主要涉及到如下三块内容:
|
这道题目主要涉及到如下三块内容:
|
||||||
1. 要统计元素出现频率
|
1. 要统计元素出现频率
|
||||||
2. 对频率排序
|
2. 对频率排序
|
||||||
|
@ -266,18 +266,17 @@ class Solution:
|
|||||||
|
|
||||||
### Go
|
### Go
|
||||||
|
|
||||||
|
**贪心**
|
||||||
```golang
|
```golang
|
||||||
func wiggleMaxLength(nums []int) int {
|
func wiggleMaxLength(nums []int) int {
|
||||||
var count,preDiff,curDiff int
|
var count, preDiff, curDiff int //初始化默认为0
|
||||||
count=1
|
count = 1 // 初始化为1,因为最小的序列是1个数
|
||||||
if len(nums) < 2 {
|
if len(nums) < 2 {
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
for i := 0; i < len(nums)-1; i++ {
|
for i := 0; i < len(nums)-1; i++ {
|
||||||
curDiff = nums[i+1] - nums[i]
|
curDiff = nums[i+1] - nums[i]
|
||||||
//如果有正有负则更新下标值||或者只有前一个元素为0(针对两个不等元素的序列也视作摆动序列,且摆动长度为2)
|
if (curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0) {
|
||||||
if (curDiff > 0 && preDiff <= 0) || (preDiff >= 0 && curDiff < 0){
|
|
||||||
preDiff=curDiff
|
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -285,6 +284,43 @@ func wiggleMaxLength(nums []int) int {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**动态规划**
|
||||||
|
```golang
|
||||||
|
func wiggleMaxLength(nums []int) int {
|
||||||
|
n := len(nums)
|
||||||
|
if n <= 1 {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
dp := make([][2]int, n)
|
||||||
|
// i 0 作为波峰的最大长度
|
||||||
|
// i 1 作为波谷的最大长度
|
||||||
|
dp[0][0] = 1
|
||||||
|
dp[0][1] = 1
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
for j := 0; j < i; j++ {
|
||||||
|
if nums[j] > nums[i] { //nums[i]为波谷
|
||||||
|
dp[i][1] = max(dp[i][1], dp[j][0]+1)
|
||||||
|
}
|
||||||
|
if nums[j] < nums[i] { //nums[i]为波峰 或者相等
|
||||||
|
dp[i][0] = max(dp[i][0], dp[j][1]+1)
|
||||||
|
}
|
||||||
|
if nums[j] == nums[i] { //添加一种情况,nums[i]为相等
|
||||||
|
dp[i][0] = max(dp[i][0], dp[j][0]) //波峰
|
||||||
|
dp[i][1] = max(dp[i][1], dp[j][1]) //波谷
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max(dp[n-1][0], dp[n-1][1])
|
||||||
|
}
|
||||||
|
func max(a, b int) int {
|
||||||
|
if a > b {
|
||||||
|
return a
|
||||||
|
} else {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Javascript
|
### Javascript
|
||||||
**贪心**
|
**贪心**
|
||||||
```Javascript
|
```Javascript
|
||||||
|
@ -417,7 +417,32 @@ var canPartition = function(nums) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Rust
|
||||||
|
|
||||||
|
```Rust
|
||||||
|
impl Solution {
|
||||||
|
fn max(a: usize, b: usize) -> usize {
|
||||||
|
if a > b { a } else { b }
|
||||||
|
}
|
||||||
|
pub fn can_partition(nums: Vec<i32>) -> bool {
|
||||||
|
let nums = nums.iter().map(|x| *x as usize).collect::<Vec<usize>>();
|
||||||
|
let mut sum = 0;
|
||||||
|
let mut dp: Vec<usize> = vec![0; 10001];
|
||||||
|
for i in 0..nums.len() {
|
||||||
|
sum += nums[i];
|
||||||
|
}
|
||||||
|
if sum % 2 == 1 { return false; }
|
||||||
|
let target = sum / 2;
|
||||||
|
for i in 0..nums.len() {
|
||||||
|
for j in (nums[i]..=target).rev() {
|
||||||
|
dp[j] = Self::max(dp[j], dp[j - nums[i]] + nums[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if dp[target] == target { return true; }
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### C:
|
### C:
|
||||||
|
@ -16,6 +16,17 @@
|
|||||||
|
|
||||||
# 思路
|
# 思路
|
||||||
|
|
||||||
|
这道题目也是 dfs bfs基础类题目。
|
||||||
|
|
||||||
|
|
||||||
|
## DFS
|
||||||
|
|
||||||
|
很多同学,写dfs其实也是凭感觉来,有的时候dfs函数中写终止条件才能过,有的时候 dfs函数不写终止添加也能过!
|
||||||
|
|
||||||
|
这里其实涉及到dfs的两种写法,
|
||||||
|
|
||||||
|
以下代码使用dfs实现,如果对dfs不太了解的话,建议先看这篇题解:[797.所有可能的路径](https://leetcode.cn/problems/all-paths-from-source-to-target/solution/by-carlsun-2-66pf/),
|
||||||
|
|
||||||
写法一,dfs只处理下一个节点
|
写法一,dfs只处理下一个节点
|
||||||
```CPP
|
```CPP
|
||||||
class Solution {
|
class Solution {
|
||||||
@ -94,3 +105,55 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
以上两种写法的区别,我在题解: [DFS,BDF 你没注意的细节都给你列出来了!LeetCode:200. 岛屿数量](https://leetcode.cn/problems/number-of-islands/solution/by-carlsun-2-n72a/)做了详细介绍。
|
||||||
|
|
||||||
|
## BFS
|
||||||
|
|
||||||
|
```CPP
|
||||||
|
class Solution {
|
||||||
|
private:
|
||||||
|
int count;
|
||||||
|
int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 四个方向
|
||||||
|
void bfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y) {
|
||||||
|
queue<int> que;
|
||||||
|
que.push(x);
|
||||||
|
que.push(y);
|
||||||
|
visited[x][y] = true; // 加入队列就意味节点是陆地可到达的点
|
||||||
|
count++;
|
||||||
|
while(!que.empty()) {
|
||||||
|
int xx = que.front();que.pop();
|
||||||
|
int yy = que.front();que.pop();
|
||||||
|
for (int i = 0 ;i < 4; i++) {
|
||||||
|
int nextx = xx + dir[i][0];
|
||||||
|
int nexty = yy + dir[i][1];
|
||||||
|
if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue; // 越界
|
||||||
|
if (!visited[nextx][nexty] && grid[nextx][nexty] == 1) { // 节点没有被访问过且是陆地
|
||||||
|
visited[nextx][nexty] = true;
|
||||||
|
count++;
|
||||||
|
que.push(nextx);
|
||||||
|
que.push(nexty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
int maxAreaOfIsland(vector<vector<int>>& grid) {
|
||||||
|
int n = grid.size(), m = grid[0].size();
|
||||||
|
vector<vector<bool>> visited = vector<vector<bool>>(n, vector<bool>(m, false));
|
||||||
|
int result = 0;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
for (int j = 0; j < m; j++) {
|
||||||
|
if (!visited[i][j] && grid[i][j] == 1) {
|
||||||
|
count = 0;
|
||||||
|
bfs(grid, visited, i, j); // 将与其链接的陆地都标记上 true
|
||||||
|
result = max(result, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
@ -290,10 +290,11 @@ func search(nums []int, target int) int {
|
|||||||
*/
|
*/
|
||||||
var search = function(nums, target) {
|
var search = function(nums, target) {
|
||||||
// right是数组最后一个数的下标,num[right]在查找范围内,是左闭右闭区间
|
// right是数组最后一个数的下标,num[right]在查找范围内,是左闭右闭区间
|
||||||
let left = 0, right = nums.length - 1;
|
let mid, left = 0, right = nums.length - 1;
|
||||||
// 当left=right时,由于nums[right]在查找范围内,所以要包括此情况
|
// 当left=right时,由于nums[right]在查找范围内,所以要包括此情况
|
||||||
while (left <= right) {
|
while (left <= right) {
|
||||||
let mid = left + Math.floor((right - left)/2);
|
// 位运算 + 防止大数溢出
|
||||||
|
mid = left + ((right - left) >> 1);
|
||||||
// 如果中间数大于目标值,要把中间数排除查找范围,所以右边界更新为mid-1;如果右边界更新为mid,那中间数还在下次查找范围内
|
// 如果中间数大于目标值,要把中间数排除查找范围,所以右边界更新为mid-1;如果右边界更新为mid,那中间数还在下次查找范围内
|
||||||
if (nums[mid] > target) {
|
if (nums[mid] > target) {
|
||||||
right = mid - 1; // 去左面闭区间寻找
|
right = mid - 1; // 去左面闭区间寻找
|
||||||
@ -316,10 +317,11 @@ var search = function(nums, target) {
|
|||||||
*/
|
*/
|
||||||
var search = function(nums, target) {
|
var search = function(nums, target) {
|
||||||
// right是数组最后一个数的下标+1,nums[right]不在查找范围内,是左闭右开区间
|
// right是数组最后一个数的下标+1,nums[right]不在查找范围内,是左闭右开区间
|
||||||
let left = 0, right = nums.length;
|
let mid, left = 0, right = nums.length;
|
||||||
// 当left=right时,由于nums[right]不在查找范围,所以不必包括此情况
|
// 当left=right时,由于nums[right]不在查找范围,所以不必包括此情况
|
||||||
while (left < right) {
|
while (left < right) {
|
||||||
let mid = left + Math.floor((right - left)/2);
|
// 位运算 + 防止大数溢出
|
||||||
|
mid = left + ((right - left) >> 1);
|
||||||
// 如果中间值大于目标值,中间值不应在下次查找的范围内,但中间值的前一个值应在;
|
// 如果中间值大于目标值,中间值不应在下次查找的范围内,但中间值的前一个值应在;
|
||||||
// 由于right本来就不在查找范围内,所以将右边界更新为中间值,如果更新右边界为mid-1则将中间值的前一个值也踢出了下次寻找范围
|
// 由于right本来就不在查找范围内,所以将右边界更新为中间值,如果更新右边界为mid-1则将中间值的前一个值也踢出了下次寻找范围
|
||||||
if (nums[mid] > target) {
|
if (nums[mid] > target) {
|
||||||
@ -340,9 +342,10 @@ var search = function(nums, target) {
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
function search(nums: number[], target: number): number {
|
function search(nums: number[], target: number): number {
|
||||||
let left: number = 0, right: number = nums.length - 1;
|
let mid: number, left: number = 0, right: number = nums.length - 1;
|
||||||
while (left <= right) {
|
while (left <= right) {
|
||||||
let mid: number = left + Math.floor((right - left) / 2);
|
// 位运算 + 防止大数溢出
|
||||||
|
mid = left + ((right - left) >> 1);
|
||||||
if (nums[mid] > target) {
|
if (nums[mid] > target) {
|
||||||
right = mid - 1;
|
right = mid - 1;
|
||||||
} else if (nums[mid] < target) {
|
} else if (nums[mid] < target) {
|
||||||
@ -359,9 +362,10 @@ function search(nums: number[], target: number): number {
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
function search(nums: number[], target: number): number {
|
function search(nums: number[], target: number): number {
|
||||||
let left: number = 0, right: number = nums.length;
|
let mid: number, left: number = 0, right: number = nums.length;
|
||||||
while (left < right) {
|
while (left < right) {
|
||||||
let mid: number = left + Math.floor((right - left) / 2);
|
// 位运算 + 防止大数溢出
|
||||||
|
mid = left +((right - left) >> 1);
|
||||||
if (nums[mid] > target) {
|
if (nums[mid] > target) {
|
||||||
right = mid;
|
right = mid;
|
||||||
} else if (nums[mid] < target) {
|
} else if (nums[mid] < target) {
|
||||||
|
@ -147,6 +147,59 @@ class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### java
|
||||||
|
|
||||||
|
```java
|
||||||
|
//方法一:采用额外的数组空间
|
||||||
|
class Solution {
|
||||||
|
public int[] sortArrayByParityII(int[] nums) {
|
||||||
|
//定义结果数组 result
|
||||||
|
int[] result = new int[nums.length];
|
||||||
|
int even = 0, odd = 1;
|
||||||
|
for(int i = 0; i < nums.length; i++){
|
||||||
|
//如果为偶数
|
||||||
|
if(nums[i] % 2 == 0){
|
||||||
|
result[even] = nums[i];
|
||||||
|
even += 2;
|
||||||
|
}else{
|
||||||
|
result[odd] = nums[i];
|
||||||
|
odd += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
```java
|
||||||
|
//方法二:不采用额外的数组空间
|
||||||
|
class Solution922 {
|
||||||
|
public int[] sortArrayByParityII(int[] nums) {
|
||||||
|
//定义双指针
|
||||||
|
int oddPoint = 1, evenPoint = 0;
|
||||||
|
//开始移动并交换,最后一层必然为相互交换后再移动或者相同直接移动
|
||||||
|
while(oddPoint < nums.length && evenPoint < nums.length){
|
||||||
|
//进行判断
|
||||||
|
if(nums[oddPoint] % 2 == 0 && nums[evenPoint] % 2 == 1){ //如果均不满足
|
||||||
|
int temp = 0;
|
||||||
|
temp = nums[oddPoint];
|
||||||
|
nums[oddPoint] = nums[evenPoint];
|
||||||
|
nums[evenPoint] = temp;
|
||||||
|
oddPoint += 2;
|
||||||
|
evenPoint += 2;
|
||||||
|
}else if(nums[oddPoint] % 2 == 0 && nums[evenPoint] % 2 == 0){ //偶数满足
|
||||||
|
evenPoint += 2;
|
||||||
|
}else if(nums[oddPoint] % 2 == 1 && nums[evenPoint] % 2 == 1){ //奇数满足
|
||||||
|
oddPoint += 2;
|
||||||
|
}else{
|
||||||
|
oddPoint += 2;
|
||||||
|
evenPoint += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nums;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Python3
|
### Python3
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
# 面试题 02.07. 链表相交
|
# 面试题 02.07. 链表相交
|
||||||
|
|
||||||
|
同:160.链表相交
|
||||||
|
|
||||||
[力扣题目链接](https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/)
|
[力扣题目链接](https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/)
|
||||||
|
|
||||||
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
|
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
|
||||||
|
25
添加0222.完全二叉树的节点个数Go版本.md
Normal file
25
添加0222.完全二叉树的节点个数Go版本.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
```go
|
||||||
|
func countNodes(root *TreeNode) int {
|
||||||
|
if root == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
q := list.New()
|
||||||
|
q.PushBack(root)
|
||||||
|
res := 0
|
||||||
|
for q.Len() > 0 {
|
||||||
|
n := q.Len()
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
node := q.Remove(q.Front()).(*TreeNode)
|
||||||
|
if node.Left != nil {
|
||||||
|
q.PushBack(node.Left)
|
||||||
|
}
|
||||||
|
if node.Right != nil {
|
||||||
|
q.PushBack(node.Right)
|
||||||
|
}
|
||||||
|
res++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
22
添加559.n叉树的最大深度Go版本.md
Normal file
22
添加559.n叉树的最大深度Go版本.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
```go
|
||||||
|
func maxDepth(root *Node) int {
|
||||||
|
if root == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
q := list.New()
|
||||||
|
q.PushBack(root)
|
||||||
|
depth := 0
|
||||||
|
for q.Len() > 0 {
|
||||||
|
n := q.Len()
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
node := q.Remove(q.Front()).(*Node)
|
||||||
|
for j := range node.Children {
|
||||||
|
q.PushBack(node.Children[j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
depth++
|
||||||
|
}
|
||||||
|
return depth
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
Reference in New Issue
Block a user