mirror of
https://github.com/chefyuan/algorithm-base.git
synced 2024-11-24 13:03:41 +00:00
Merge branch 'main' of github.com:chefyuan/algorithm-base
This commit is contained in:
commit
d10b9b757f
@ -40,6 +40,8 @@
|
|||||||
|
|
||||||
#### **题目代码**
|
#### **题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
public boolean search(int[] nums, int target) {
|
public boolean search(int[] nums, int target) {
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
@ -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]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
##
|
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
@ -94,6 +94,8 @@ 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) {
|
||||||
//这里需要注意,循环条件
|
//这里需要注意,循环条件
|
||||||
@ -115,6 +117,29 @@ target < nums[mid] 则在左半区间继续进行搜索,即 right = mid -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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
二分查找的思路及代码已经理解了,那么我们来看一下实现时容易出错的地方
|
二分查找的思路及代码已经理解了,那么我们来看一下实现时容易出错的地方
|
||||||
|
|
||||||
1.计算 mid 时 ,不能使用 (left + right )/ 2,否则有可能会导致溢出
|
1.计算 mid 时 ,不能使用 (left + right )/ 2,否则有可能会导致溢出
|
||||||
@ -127,6 +152,8 @@ 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) {
|
||||||
|
|
||||||
@ -147,3 +174,26 @@ public static int binarySearch(int[] nums,int target,int left, int right) {
|
|||||||
return -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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
|
|
||||||
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) {
|
||||||
|
|
||||||
@ -59,6 +61,32 @@ public static int lowBoundnum(int[] nums,int target,int left, int right) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
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,6 +95,8 @@ 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) {
|
||||||
|
|
||||||
@ -91,3 +121,29 @@ public static int upperBoundnum(int[] nums,int target,int left, int right) {
|
|||||||
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Loading…
Reference in New Issue
Block a user