diff --git a/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md b/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md
index 04f5eaf7..97b9a9b6 100644
--- a/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md
+++ b/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md
@@ -14,7 +14,7 @@
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶:你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?
-
+
示例 1:
* 输入:nums = [5,7,7,8,8,10], target = 8
@@ -173,8 +173,105 @@ private:
## Java
```java
+class Solution {
+ int[] searchRange(int[] nums, int target) {
+ int leftBorder = getLeftBorder(nums, target);
+ int rightBorder = getRightBorder(nums, target);
+ // 情况一
+ if (leftBorder == -2 || rightBorder == -2) return new int[]{-1, -1};
+ // 情况三
+ if (rightBorder - leftBorder > 1) return new int[]{leftBorder + 1, rightBorder - 1};
+ // 情况二
+ return new int[]{-1, -1};
+ }
+
+ int getRightBorder(int[] nums, int target) {
+ int left = 0;
+ int right = nums.length - 1;
+ int rightBorder = -2; // 记录一下rightBorder没有被赋值的情况
+ while (left <= right) {
+ int middle = left + ((right - left) / 2);
+ if (nums[middle] > target) {
+ right = middle - 1;
+ } else { // 寻找右边界,nums[middle] == target的时候更新left
+ left = middle + 1;
+ rightBorder = left;
+ }
+ }
+ return rightBorder;
+ }
+
+ int getLeftBorder(int[] nums, int target) {
+ int left = 0;
+ int right = nums.length - 1;
+ int leftBorder = -2; // 记录一下leftBorder没有被赋值的情况
+ while (left <= right) {
+ int middle = left + ((right - left) / 2);
+ if (nums[middle] >= target) { // 寻找左边界,nums[middle] == target的时候更新right
+ right = middle - 1;
+ leftBorder = right;
+ } else {
+ left = middle + 1;
+ }
+ }
+ return leftBorder;
+ }
+}
```
+```java
+// 解法2
+// 1、首先,在 nums 数组中二分查找 target;
+// 2、如果二分查找失败,则 binarySearch 返回 -1,表明 nums 中没有 target。此时,searchRange 直接返回 {-1, -1};
+// 3、如果二分查找失败,则 binarySearch 返回 nums 中 为 target 的一个下标。然后,通过左右滑动指针,来找到符合题意的区间
+
+class Solution {
+ public int[] searchRange(int[] nums, int target) {
+ int index = binarySearch(nums, target); // 二分查找
+
+ if (index == -1) { // nums 中不存在 target,直接返回 {-1, -1}
+ return new int[] {-1, -1}; // 匿名数组
+ }
+ // nums 中存在 targe,则左右滑动指针,来找到符合题意的区间
+ int left = index;
+ int right = index;
+ // 向左滑动,找左边界
+ while (left - 1 >= 0 && nums[left - 1] == nums[index]) { // 防止数组越界。逻辑短路,两个条件顺序不能换
+ left--;
+ }
+ // 向左滑动,找右边界
+ while (right + 1 < nums.length && nums[right + 1] == nums[index]) { // 防止数组越界。
+ right++;
+ }
+ return new int[] {left, right};
+ }
+
+ /**
+ * 二分查找
+ * @param nums
+ * @param target
+ */
+ public int binarySearch(int[] nums, int target) {
+ int left = 0;
+ int right = nums.length - 1; // 不变量:左闭右闭区间
+
+ while (left <= right) { // 不变量:左闭右闭区间
+ int mid = left + (right - left) / 2;
+ if (nums[mid] == target) {
+ return mid;
+ } else if (nums[mid] < target) {
+ left = mid + 1;
+ } else {
+ right = mid - 1; // 不变量:左闭右闭区间
+ }
+ }
+ return -1; // 不存在
+ }
+}
+```
+
+
+
## Python
```python
@@ -196,4 +293,3 @@ private:
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
-
diff --git a/problems/0141.环形链表.md b/problems/0141.环形链表.md
index 4a40f953..0871202d 100644
--- a/problems/0141.环形链表.md
+++ b/problems/0141.环形链表.md
@@ -14,7 +14,7 @@
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
-
+

# 思路
@@ -74,6 +74,21 @@ public:
## Java
```java
+public class Solution {
+ public boolean hasCycle(ListNode head) {
+ ListNode fast = head;
+ ListNode slow = head;
+ // 空链表、单节点链表一定不会有环
+ while (fast != null && fast.next != null) {
+ fast = fast.next.next; // 快指针,一次移动两步
+ slow = slow.next; // 慢指针,一次移动一步
+ if (fast == slow) { // 快慢指针相遇,表明有环
+ return true;
+ }
+ }
+ return false; // 正常走到链表末尾,表明没有环
+ }
+}
```
## Python
diff --git a/problems/0283.移动零.md b/problems/0283.移动零.md
index 56f96b2f..8db42a0a 100644
--- a/problems/0283.移动零.md
+++ b/problems/0283.移动零.md
@@ -64,6 +64,21 @@ public:
Java:
+```java
+public void moveZeroes(int[] nums) {
+ int slow = 0;
+ for (int fast = 0; fast < nums.length; fast++) {
+ if (nums[fast] != 0) {
+ nums[slow++] = nums[fast];
+ }
+ }
+ // 后面的元素全变成 0
+ for (int j = slow; j < nums.length; j++) {
+ nums[j] = 0;
+ }
+ }
+```
+
Python:
```python
diff --git a/problems/0941.有效的山脉数组.md b/problems/0941.有效的山脉数组.md
index 6dbc3da2..167cfb1a 100644
--- a/problems/0941.有效的山脉数组.md
+++ b/problems/0941.有效的山脉数组.md
@@ -18,7 +18,7 @@ https://leetcode-cn.com/problems/valid-mountain-array/
C++代码如下:
-```
+```c++
class Solution {
public:
bool validMountainArray(vector& A) {
@@ -38,6 +38,33 @@ public:
}
};
```
+Java 版本如下:
+
+```java
+class Solution {
+ public boolean validMountainArray(int[] arr) {
+ if (arr.length < 3) { // 此时,一定不是有效的山脉数组
+ return false;
+ }
+ // 双指针
+ int left = 0;
+ int right = arr.length - 1;
+ // 注意防止指针越界
+ while (left + 1 < arr.length && arr[left] < arr[left + 1]) {
+ left++;
+ }
+ // 注意防止指针越界
+ while (right > 0 && arr[right] < arr[right - 1]) {
+ right--;
+ }
+ // 如果left或者right都在起始位置,说明不是山峰
+ if (left == right && left != 0 && right != arr.length - 1) {
+ return true;
+ }
+ return false;
+ }
+}
+```
+
如果想系统学一学双指针的话, 可以看一下这篇[双指针法:总结篇!](https://mp.weixin.qq.com/s/_p7grwjISfMh0U65uOyCjA)
-
diff --git a/problems/1207.独一无二的出现次数.md b/problems/1207.独一无二的出现次数.md
index 377d9ebf..c1720430 100644
--- a/problems/1207.独一无二的出现次数.md
+++ b/problems/1207.独一无二的出现次数.md
@@ -77,6 +77,28 @@ public:
Java:
+```java
+class Solution {
+ public boolean uniqueOccurrences(int[] arr) {
+ int[] count = new int[2002];
+ for (int i = 0; i < arr.length; i++) {
+ count[arr[i] + 1000]++; // 防止负数作为下标
+ }
+ boolean[] flag = new boolean[1002]; // 标记相同频率是否重复出现
+ for (int i = 0; i <= 2000; i++) {
+ if (count[i] > 0) {
+ if (flag[count[i]] == false) {
+ flag[count[i]] = true;
+ } else {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+}
+```
+
Python:
Go:
@@ -89,4 +111,3 @@ JavaScript:
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
-