0034、0035、0036 solved

This commit is contained in:
程序员吴师兄 2020-05-06 10:30:06 +08:00
parent ae6f9cd1ae
commit bbd0d2b3a3
15 changed files with 427 additions and 0 deletions

View File

@ -0,0 +1,81 @@
# LeetCode 34 号问题在排序数组中查找元素的第一个和最后一个位置
题目来源于 LeetCode 上第 34 号问题find-first-and-last-position-of-element-in-sorted-array题目难度为 中等
### 题目描述
给定一个按照升序排列的整数数组 **nums**和一个目标值 **target**找出给定目标值在数组中的开始位置和结束位置
你的算法时间复杂度必须是 **O(log n)** 级别
如果数组中不存在目标值返回 [-1, -1]
**示例:**
```
输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]
```
```
输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]
```
### 题目解析
题目中要求了时间复杂度为O(log n),这就很清楚要使用二分查找法了
首先定义两个指针变量分别存储左右两个位置的索引首先去找目标值的最左面的索引,通过循环为了防止元素丢失,每次保留最右面的元素,左侧的指针移动时+1在循环结束的时候判断一下数组中是否包括目标值,不包括的话直接退出
右面的跟左侧相同只不过正好相反
### 动画描述
![](..\Animation\在排序数组中查找元素的第一个和最后一个位置.gif)
### 代码实现
```java
// 34. 下一个排列
// https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/
// 时间复杂度O(n)
// 空间复杂度O(1)
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] res = new int[] { -1, -1 };
int left = 0;
int right = nums.length - 1;
int l = left;
int r = right;
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
if (left>right||nums[left]!=target) {
return new int[]{-1,-1};
}
while (l < r) {
int mid = (l + r) / 2 + 1;
if (nums[mid] > target) {
r = mid - 1;
} else {
l = mid;
}
}
if (left > right || left > r) {
return new int[] { -1, -1 };
} else {
return new int[] { left, r };
}
}
}
```
![](../../Pictures/qrcode.jpg)

View File

@ -0,0 +1,33 @@
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] res = new int[] { -1, -1 };
int left = 0;
int right = nums.length - 1;
int l = left;
int r = right;
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
if (left>right||nums[left]!=target) {
return new int[]{-1,-1};
}
while (l < r) {
int mid = (l + r) / 2 + 1;
if (nums[mid] > target) {
r = mid - 1;
} else {
l = mid;
}
}
if (left > right || left > r) {
return new int[] { -1, -1 };
} else {
return new int[] { left, r };
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

View File

@ -0,0 +1,113 @@
# LeetCode 35 号问题搜索插入位置
> 本文首发于公众号图解面试算法 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一
>
> 同步博客https://www.algomooc.com
题目来源于 LeetCode 35 号问题搜索插入位置.
## 题目
给定一个排序数组和一个目标值在数组中找到目标值并返回其索引如果目标值不存在于数组中返回它将会被按顺序插入的位置
你可以假设数组中无重复元素
示例 1:
```
输入: [1,3,5,6], 5
输出: 2
```
示例 2:
```
输入: [1,3,5,6], 2
输出: 1
```
示例 3:
```
输入: [1,3,5,6], 7
输出: 4
```
示例 4:
```
输入: [1,3,5,6], 0
输出: 0
```
## 思路解析
### 暴力循环法
这个题看起来就是很简单的就是一道考验查找算法的题目最简单的就是暴力查找了
#### 思路
遍历这个数组然后如果当前值和目标值target一致或小于目标值target那么就return 当前下标这种解法的时间复杂度是O(N)
### 动画理解
![](../Animation/暴力查找.gif)
#### 代码实现
```java
//时间复杂度O(n)
//空间复杂度O(1)
class Solution {
public int searchInsert(int[] nums, int target) {
int i=0;
for(;i<nums.length;i++){
if (nums[i]>=target){
break;
}
}
return i;
}
}
```
### 二分法
#### 思路
除了暴力法我们在排序数组中查找值还可以用的一种方法是二分法思路还是和改良的暴力循环法一样先找到左右边界然后计算每次可以省出一半的时间时间复杂度为O(logn)
#### 代码实现
```java
//时间复杂度O(lon(n))
//空间复杂度O(1)
class Solution {
public int searchInsert(int[] nums, int target) {
if (target>nums[nums.length-1]) {
return nums.length;
}
int left=0;
int right=nums.length-1;
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
}
```
![](../../Pictures/qrcode.jpg)

View File

@ -0,0 +1,11 @@
class Solution1 {
public int searchInsert(int[] nums, int target) {
int i=0;
for(;i<nums.length;i++){
if (nums[i]>=target){
break;
}
}
return i;
}
}

View File

@ -0,0 +1,21 @@
//时间复杂度O(lon(n))
//空间复杂度O(1)
class Solution2 {
public int searchInsert(int[] nums, int target) {
if (target>nums[nums.length-1]) {
return nums.length;
}
int left=0;
int right=nums.length-1;
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

Binary file not shown.

View File

@ -0,0 +1,134 @@
# LeetCode 36 号问题有效的数独
> 本文首发于公众号图解面试算法 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一
>
> 同步博客https://www.algomooc.com
题目来源于 LeetCode 36 号问题有效的数独.
## 题目
判断一个 9x9 的数独是否有效只需要根据以下规则验证已经填入的数字是否有效即可
数字 1-9 在每一行只能出现一次
数字 1-9 在每一列只能出现一次
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次
示例 1:
```
输入:
[
["5","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]
]
输出: true
```
示例 2:
```
输入:
[
["8","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]
]
输出: false
解释: 除了第一行的第一个数字从 5 改为 8 以外空格内其他数字均与 示例1 相同
但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的
```
示例 3:
```
输入: [1,3,5,6], 7
输出: 4
```
示例 4:
```
输入: [1,3,5,6], 0
输出: 0
```
## 思路解析
### 一次遍历法
#### 思路
这道题因为需要判断数值是否存在所以用Hash Map是一个很好的选择
因为每一行每一列每一格都是需要单独进行判断的所以需要建立三个长度为9的HashMap数组分别存放行格的数值
通过一个二层循环遍历这个9*9的数组,把当前格的数值存放到对应的HashMap中判断之前是否已经存放过了如果已经存放过那就退出返回false如果是.的话那就跳过这样只需要遍历一边就可以了
### 动画理解
![](../Animation/HashMap.gif)
#### 代码实现
```java
//时间复杂度O(n)
//空间复杂度O(1)
class Solution {
public boolean isValidSudoku(char[][] board) {
HashMap[] row = new HashMap[9];
HashMap[] column = new HashMap[9];
HashMap[] box = new HashMap[9];
for (int i = 0; i < 9; i++) {
row[i] = new HashMap(9);
column[i] = new HashMap(9);
box[i] = new HashMap(9);
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == '.') {
continue;
}
int boxIndex=i / 3 * 3 + j / 3;
if ((boolean) row[i].getOrDefault(board[i][j], true)) {
return false;
}
if ((boolean) column[j].getOrDefault(board[i][j], true)) {
return false;
}
if ((boolean) box[boxIndex].getOrDefault(board[i][j], true)) {
return false;
}
row[i].put(board[i][j], false);
column[j].put(board[i][j], false);
box[boxIndex].put(board[i][j], false);
}
}
return true;
}
}
```
![](../../Pictures/qrcode.jpg)

34
0036-valid-sudoku/Code/1.java Executable file
View File

@ -0,0 +1,34 @@
class Solution {
public boolean isValidSudoku(char[][] board) {
HashMap[] row = new HashMap[9];
HashMap[] column = new HashMap[9];
HashMap[] box = new HashMap[9];
for (int i = 0; i < 9; i++) {
row[i] = new HashMap(9);
column[i] = new HashMap(9);
box[i] = new HashMap(9);
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == '.') {
continue;
}
int boxIndex=i / 3 * 3 + j / 3;
if ((boolean) row[i].getOrDefault(board[i][j], true)) {
return false;
}
if ((boolean) column[j].getOrDefault(board[i][j], true)) {
return false;
}
if ((boolean) box[boxIndex].getOrDefault(board[i][j], true)) {
return false;
}
row[i].put(board[i][j], false);
column[j].put(board[i][j], false);
box[boxIndex].put(board[i][j], false);
}
}
return true;
}
}