Merge branch 'main' of github.com:chefyuan/algorithm-base

This commit is contained in:
chefyuan 2021-08-27 20:23:48 +08:00
commit d10b9b757f
8 changed files with 180 additions and 235 deletions

View File

@ -40,10 +40,12 @@
#### **题目代码** #### **题目代码**
Java Code:
```java ```java
class Solution { class Solution {
public boolean search(int[] nums, int target) { public boolean search(int[] nums, int target) {
int left = 0; int left = 0;
int right = nums.length - 1; int right = nums.length - 1;
while (left <= right) { while (left <= right) {
int mid = left+((right-left)>>1); int mid = left+((right-left)>>1);
@ -73,35 +75,3 @@ class Solution {
} }
} }
``` ```
Go Code:
```go
func search(nums []int, target int) bool {
l, r := 0, len(nums) - 1
for l <= r {
m := l + (r - l) / 2
if nums[m] == target {
return true
}
// 先判断哪边是递增的再查找范围
if nums[m] == nums[l] {
l++
} else if nums[l] < nums[m] {
// 判断target是否在有序的那边就行了
if nums[l] <= target && target < nums[m] {
r = m - 1
} else {
l = m + 1
}
} else if nums[l] > nums[m] {
if nums[m] < target && target <= nums[r] {
l = m + 1
} else {
r = m - 1
}
}
}
return false
}
```

View File

@ -104,23 +104,3 @@ public:
} }
}; };
``` ```
Go Code:
```go
func findMin(nums []int) int {
l, r := 0, len(nums) - 1
for l < r {
if nums[l] < nums[r] {
return nums[l]
}
m := l + (r - l) / 2
if nums[l] > nums[m] {
r = m
} else {
l = m + 1
}
}
return nums[l]
}
```

View File

@ -89,6 +89,8 @@
#### 题目代码 #### 题目代码
Java Code:
```java ```java
class Solution { class Solution {
public int search(int[] nums, int target) { public int search(int[] nums, int target) {
@ -126,35 +128,3 @@ class Solution {
} }
} }
``` ```
Go Code:
```go
func search(nums []int, target int) int {
l, r := 0, len(nums) - 1
for l <= r {
m := (l + r) / 2
if target == nums[m] {
return m
}
// 先判断哪边是有序的
if nums[m] < nums[r] {
// 再判断target在左右哪边
if target > nums[m] && target <= nums[r] {
l = m + 1
} else {
r = m - 1
}
} else {
if target < nums[m] && target >= nums[l] {
r = m - 1
} else {
l = m + 1
}
}
}
return -1
}
```
##

View File

@ -122,6 +122,8 @@ int upperBound(int[] nums, int target) {
#### **题目完整代码** #### **题目完整代码**
Java Code:
```java ```java
class Solution { class Solution {
public int[] searchRange (int[] nums, int target) { public int[] searchRange (int[] nums, int target) {
@ -166,45 +168,3 @@ class Solution {
} }
} }
``` ```
Go Code:
```go
func searchRange(nums []int, target int) []int {
upper := upperBound(nums, target)
lower := lowerBound(nums, target)
if (upper < lower) {
return []int{-1, -1}
}
return []int{lower, upper}
}
// upperBound 计算上边界
func upperBound(nums []int, target int) int {
l, r := 0, len(nums) - 1
for l <= r {
m := l + (r - l) / 2
if target >= nums[m] {
l = m + 1
} else if target < nums[m] {
r = m - 1
}
}
return r
}
// lowerBound 计算下边界
func lowerBound(nums []int, target int) int {
l, r := 0, len(nums) - 1
for l <= r {
m := l + (r - l) / 2
if target <= nums[m] {
r = m - 1
} else if target > nums[m] {
l = m + 1
}
}
return l
}
```

View File

@ -40,6 +40,8 @@
#### 题目代码 #### 题目代码
Java Code:
```java ```java
class Solution { class Solution {
public int searchInsert(int[] nums, int target) { public int searchInsert(int[] nums, int target) {
@ -67,21 +69,3 @@ class Solution {
``` ```
Go Code: Go Code:
```go
func searchInsert(nums []int, target int) int {
l, r := 0, len(nums) - 1
for l <= r {
m := l + (r - l) / 2
if target == nums[m] {
return m
}
if target < nums[m] {
r = m - 1
} else if target > nums[m] {
l = m + 1
}
}
return l
}
```

View File

@ -94,25 +94,50 @@ target < nums[mid] 则在左半区间继续进行搜索,即 right = mid -1
下面我们来看一下二分查找的代码可以认真思考一下 if 语句的条件每个都没有简写 下面我们来看一下二分查找的代码可以认真思考一下 if 语句的条件每个都没有简写
Java Code:
```java ```java
public static int binarySearch(int[] nums,int target,int left, int right) { public static int binarySearch(int[] nums,int target,int left, int right) {
//这里需要注意循环条件 //这里需要注意循环条件
while (left <= right) { while (left <= right) {
//这里需要注意计算mid //这里需要注意计算mid
int mid = left + ((right - left) >> 1); int mid = left + ((right - left) >> 1);
if (nums[mid] == target) { if (nums[mid] == target) {
return mid; return mid;
}else if (nums[mid] < target) { }else if (nums[mid] < target) {
//这里需要注意移动左指针 //这里需要注意移动左指针
left = mid + 1; left = mid + 1;
}else if (nums[mid] > target) { }else if (nums[mid] > target) {
//这里需要注意移动右指针 //这里需要注意移动右指针
right = mid - 1; right = mid - 1;
}
} }
//没有找到该元素返回 -1
return -1;
} }
//没有找到该元素返回 -1
return -1;
}
```
Go Code:
```go
func binarySearch(nums []int, target, left, right int) int {
//这里需要注意循环条件
for left <= right {
//这里需要注意计算mid
mid := left + ((right - left) >> 1)
if nums[mid] == target {
return mid
} else if nums[mid] < target {
//这里需要注意移动左指针
left = mid + 1
} else if nums[mid] > target {
//这里需要注意移动右指针
right = mid - 1
}
}
//没有找到该元素返回 -1
return -1
}
``` ```
二分查找的思路及代码已经理解了那么我们来看一下实现时容易出错的地方 二分查找的思路及代码已经理解了那么我们来看一下实现时容易出错的地方
@ -127,23 +152,48 @@ target < nums[mid] 则在左半区间继续进行搜索,即 right = mid -1
下面我们来看一下二分查找的递归写法 下面我们来看一下二分查找的递归写法
Java Code:
```java ```java
public static int binarySearch(int[] nums,int target,int left, int right) { public static int binarySearch(int[] nums,int target,int left, int right) {
if (left <= right) { if (left <= right) {
int mid = left + ((right - left) >> 1); int mid = left + ((right - left) >> 1);
if (nums[mid] == target) { if (nums[mid] == target) {
//查找成功 //查找成功
return mid; return mid;
}else if (nums[mid] > target) { }else if (nums[mid] > target) {
//新的区间,左半区间 //新的区间,左半区间
return binarySearch(nums,target,left,mid-1); return binarySearch(nums,target,left,mid-1);
}else if (nums[mid] < target) { }else if (nums[mid] < target) {
//新的区间右半区间 //新的区间右半区间
return binarySearch(nums,target,mid+1,right); return binarySearch(nums,target,mid+1,right);
}
} }
//不存在返回-1
return -1;
} }
//不存在返回-1
return -1;
}
```
Go Code:
```go
func binarySearch(nums []int, target, left, right int) int {
if left <= right {
mid := left + ((right - left) >> 1)
if nums[mid] == target {
//查找成功
return mid
} else if nums[mid] > target {
//新的区间,左半区间
return binarySearch(nums, target, left, mid-1)
} else if nums[mid] < target {
//新的区间右半区间
return binarySearch(nums, target, mid+1, right)
}
}
//不存在返回-1
return -1
}
``` ```

View File

@ -52,6 +52,8 @@
#### 题目代码 #### 题目代码
Java Code:
```java ```java
class Solution { class Solution {
public boolean searchMatrix(int[][] matrix, int target) { public boolean searchMatrix(int[][] matrix, int target) {
@ -83,30 +85,3 @@ class Solution {
} }
} }
``` ```
Go Code:
```go
func searchMatrix(matrix [][]int, target int) bool {
if len(matrix) == 0 {
return false
}
row, col := len(matrix), len(matrix[0])
// 将二维数组拉平为一维
l, r := 0, row * col - 1
for l <= r {
m := l + (r - l) / 2
// 将一维的坐标转换为二维
x, y := m / col, m % col
if matrix[x][y] == target {
return true
} else if matrix[x][y] < target {
l = m + 1
} else if matrix[x][y] > target {
// 二分查找时把所有的情况都要写出来避免直接else
r = m - 1
}
}
return false
}
```

View File

@ -34,29 +34,57 @@
OK!我们到这一步就能把这个变种给整的明明白白的了下面我们看一哈程序代码吧也是非常简单的 OK!我们到这一步就能把这个变种给整的明明白白的了下面我们看一哈程序代码吧也是非常简单的
Java Code:
```java ```java
public static int lowBoundnum(int[] nums,int target,int left, int right) { public static int lowBoundnum(int[] nums,int target,int left, int right) {
while (left <= right) { while (left <= right) {
//求中间值 //求中间值
int mid = left + ((right - left) >> 1); int mid = left + ((right - left) >> 1);
//大于目标值的情况 //大于目标值的情况
if (nums[mid] > target) { if (nums[mid] > target) {
//返回 mid //返回 mid
if (mid == 0 || nums[mid-1] <= target) { if (mid == 0 || nums[mid-1] <= target) {
return mid; return mid;
}
else{
right = mid -1;
}
} else if (nums[mid] <= target){
left = mid + 1;
} }
else{
right = mid -1;
}
} else if (nums[mid] <= target){
left = mid + 1;
} }
//所有元素都小于目标元素
return -1;
} }
//所有元素都小于目标元素
return -1;
}
```
Go Code:
```go
func lowBoundnum(nums []int, target, left, right int) int {
for (left <= right) {
//求中间值
mid := left + ((right - left) >> 1);
//大于目标值的情况
if (nums[mid] > target) {
//返回 mid
if (mid == 0 || nums[mid-1] <= target) {
return mid
}else{
right = mid -1
}
} else if (nums[mid] <= target){
left = mid + 1
}
}
//所有元素都小于目标元素
return -1
}
``` ```
## **找出最后一个小于目标元素的索引** ## **找出最后一个小于目标元素的索引**
@ -67,27 +95,55 @@ public static int lowBoundnum(int[] nums,int target,int left, int right) {
查找最后一个小于目标数的元素比如我们的目标数为 7 此时他前面的数为 6最后一个 6 的索引为 5此时我们返回 5 即可如果目标数元素为 12那么我们最后一个元素为 11仍小于目标数那么我们此时返回 8即可这个变种其实算是上面变种的相反情况上面的会了这个也完全可以搞定了下面我们看一下代码吧 查找最后一个小于目标数的元素比如我们的目标数为 7 此时他前面的数为 6最后一个 6 的索引为 5此时我们返回 5 即可如果目标数元素为 12那么我们最后一个元素为 11仍小于目标数那么我们此时返回 8即可这个变种其实算是上面变种的相反情况上面的会了这个也完全可以搞定了下面我们看一下代码吧
Java Code:
```java ```java
public static int upperBoundnum(int[] nums,int target,int left, int right) { public static int upperBoundnum(int[] nums,int target,int left, int right) {
while (left <= right) { while (left <= right) {
int mid = left + ((right - left) >> 1); int mid = left + ((right - left) >> 1);
//小于目标值 //小于目标值
if (nums[mid] < target) { if (nums[mid] < target) {
//看看是不是当前区间的最后一位如果当前小于后面一位大于返回当前值即可 //看看是不是当前区间的最后一位如果当前小于后面一位大于返回当前值即可
if (mid == right || nums[mid+1] >= target) { if (mid == right || nums[mid+1] >= target) {
return mid; return mid;
}
else{
left = mid + 1;
}
} else if (nums[mid] >= target){
right = mid - 1;
} }
else{
left = mid + 1;
}
} else if (nums[mid] >= target){
right = mid - 1;
} }
//没有查询到的情况
return -1;
} }
//没有查询到的情况
return -1;
}
```
Go Code:
```go
func upperBoundnum(nums []int, target, left, right int) int {
for left <= right {
mid := left + ((right - left) >> 1)
//小于目标值
if nums[mid] < target {
//看看是不是当前区间的最后一位如果当前小于后面一位大于返回当前值即可
if mid == right || nums[mid+1] >= target {
return mid
} else {
left = mid + 1
}
} else if nums[mid] >= target {
right = mid - 1
}
}
//没有查询到的情况
return -1
}
``` ```