Commit bbd0d2b3 authored by 程序员吴师兄's avatar 程序员吴师兄
Browse files

0034、0035、0036 solved

parent ae6f9cd1
# 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)
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 };
}
}
}
\ No newline at end of file
# 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)
\ No newline at end of file
class Solution1 {
public int searchInsert(int[] nums, int target) {
int i=0;
for(;i<nums.length;i++){
if (nums[i]>=target){
break;
}
}
return i;
}
}
\ No newline at end of file
//时间复杂度: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;
}
}
\ No newline at end of file
# 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)
\ No newline at end of file
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;
}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment