mirror of
https://github.com/chefyuan/algorithm-base.git
synced 2024-12-26 04:18:59 +00:00
Merge branch 'main' of github.com:chefyuan/algorithm-base
This commit is contained in:
commit
d10b9b757f
@ -40,10 +40,12 @@
|
||||
|
||||
#### **题目代码**
|
||||
|
||||
Java Code:
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
public boolean search(int[] nums, int target) {
|
||||
int left = 0;
|
||||
int left = 0;
|
||||
int right = nums.length - 1;
|
||||
while (left <= right) {
|
||||
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
|
||||
}
|
||||
```
|
||||
|
@ -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
|
||||
class Solution {
|
||||
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
|
||||
class Solution {
|
||||
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
|
||||
class Solution {
|
||||
public int searchInsert(int[] nums, int target) {
|
||||
@ -67,21 +69,3 @@ class Solution {
|
||||
```
|
||||
|
||||
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,25 +94,50 @@ target < nums[mid] 则在左半区间继续进行搜索,即 right = mid -1;
|
||||
|
||||
下面我们来看一下二分查找的代码,可以认真思考一下 if 语句的条件,每个都没有简写。
|
||||
|
||||
Java Code:
|
||||
|
||||
```java
|
||||
public static int binarySearch(int[] nums,int target,int left, int right) {
|
||||
//这里需要注意,循环条件
|
||||
while (left <= right) {
|
||||
//这里需要注意,计算mid
|
||||
int 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;
|
||||
}
|
||||
public static int binarySearch(int[] nums,int target,int left, int right) {
|
||||
//这里需要注意,循环条件
|
||||
while (left <= right) {
|
||||
//这里需要注意,计算mid
|
||||
int 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
|
||||
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
|
||||
public static int binarySearch(int[] nums,int target,int left, int right) {
|
||||
|
||||
if (left <= right) {
|
||||
int 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);
|
||||
}
|
||||
if (left <= right) {
|
||||
int 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;
|
||||
}
|
||||
//不存在返回-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
|
||||
class Solution {
|
||||
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,29 +34,57 @@
|
||||
|
||||
OK!我们到这一步就能把这个变种给整的明明白白的了,下面我们看一哈程序代码吧,也是非常简单的。
|
||||
|
||||
Java Code:
|
||||
|
||||
```java
|
||||
public static int lowBoundnum(int[] nums,int target,int left, int right) {
|
||||
|
||||
while (left <= right) {
|
||||
//求中间值
|
||||
int 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;
|
||||
while (left <= right) {
|
||||
//求中间值
|
||||
int 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;
|
||||
}
|
||||
//所有元素都小于目标元素
|
||||
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,即可。这个变种其实算是上面变种的相反情况,上面的会了,这个也完全可以搞定了,下面我们看一下代码吧。
|
||||
|
||||
Java Code:
|
||||
|
||||
```java
|
||||
public static int upperBoundnum(int[] nums,int target,int left, int right) {
|
||||
|
||||
while (left <= right) {
|
||||
while (left <= right) {
|
||||
|
||||
int 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;
|
||||
int 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;
|
||||
}
|
||||
//没有查询到的情况
|
||||
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