diff --git a/0034-find-first-and-last-position-of-element-in-sorted-array/Animation/在排序数组中查找元素的第一个和最后一个位置.gif b/0034-find-first-and-last-position-of-element-in-sorted-array/Animation/在排序数组中查找元素的第一个和最后一个位置.gif new file mode 100755 index 0000000..a7591e2 Binary files /dev/null and b/0034-find-first-and-last-position-of-element-in-sorted-array/Animation/在排序数组中查找元素的第一个和最后一个位置.gif differ diff --git a/0034-find-first-and-last-position-of-element-in-sorted-array/Article/0034-find-first-and-last-position-of-element-in-sorted-array.md b/0034-find-first-and-last-position-of-element-in-sorted-array/Article/0034-find-first-and-last-position-of-element-in-sorted-array.md new file mode 100755 index 0000000..7acd768 --- /dev/null +++ b/0034-find-first-and-last-position-of-element-in-sorted-array/Article/0034-find-first-and-last-position-of-element-in-sorted-array.md @@ -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) diff --git a/0034-find-first-and-last-position-of-element-in-sorted-array/Code/1.java b/0034-find-first-and-last-position-of-element-in-sorted-array/Code/1.java new file mode 100755 index 0000000..0fdf1b3 --- /dev/null +++ b/0034-find-first-and-last-position-of-element-in-sorted-array/Code/1.java @@ -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 }; + } + } +} \ No newline at end of file diff --git a/0035-search-insert-position/Animation/~$搜索插入位置.pptx b/0035-search-insert-position/Animation/~$搜索插入位置.pptx new file mode 100755 index 0000000..2dc2a06 Binary files /dev/null and b/0035-search-insert-position/Animation/~$搜索插入位置.pptx differ diff --git a/0035-search-insert-position/Animation/二分查找.gif b/0035-search-insert-position/Animation/二分查找.gif new file mode 100755 index 0000000..ea0e2d6 Binary files /dev/null and b/0035-search-insert-position/Animation/二分查找.gif differ diff --git a/0035-search-insert-position/Animation/二分查找.mp4 b/0035-search-insert-position/Animation/二分查找.mp4 new file mode 100755 index 0000000..b6d41ed Binary files /dev/null and b/0035-search-insert-position/Animation/二分查找.mp4 differ diff --git a/0035-search-insert-position/Animation/暴力查找.gif b/0035-search-insert-position/Animation/暴力查找.gif new file mode 100755 index 0000000..db609fe Binary files /dev/null and b/0035-search-insert-position/Animation/暴力查找.gif differ diff --git a/0035-search-insert-position/Animation/暴力查找.mp4 b/0035-search-insert-position/Animation/暴力查找.mp4 new file mode 100755 index 0000000..03a22f1 Binary files /dev/null and b/0035-search-insert-position/Animation/暴力查找.mp4 differ diff --git a/0035-search-insert-position/Article/0035-search-insert-position.md b/0035-search-insert-position/Article/0035-search-insert-position.md new file mode 100755 index 0000000..4ac3ec6 --- /dev/null +++ b/0035-search-insert-position/Article/0035-search-insert-position.md @@ -0,0 +1,113 @@ +# LeetCode 第 35 号问题:搜索插入位置 + +> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode ]() 系列文章之一。 +> +> 同步博客: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=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 diff --git a/0035-search-insert-position/Code/1.java b/0035-search-insert-position/Code/1.java new file mode 100755 index 0000000..5d07563 --- /dev/null +++ b/0035-search-insert-position/Code/1.java @@ -0,0 +1,11 @@ +class Solution1 { + public int searchInsert(int[] nums, int target) { + int i=0; + for(;i=target){ + break; + } + } + return i; + } +} \ No newline at end of file diff --git a/0035-search-insert-position/Code/2.java b/0035-search-insert-position/Code/2.java new file mode 100755 index 0000000..f45f9bc --- /dev/null +++ b/0035-search-insert-position/Code/2.java @@ -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; + + } +} \ No newline at end of file diff --git a/0036-valid-sudoku/Animation/HashMap.gif b/0036-valid-sudoku/Animation/HashMap.gif new file mode 100755 index 0000000..9dcb49b Binary files /dev/null and b/0036-valid-sudoku/Animation/HashMap.gif differ diff --git a/0036-valid-sudoku/Animation/HashMap.mp4 b/0036-valid-sudoku/Animation/HashMap.mp4 new file mode 100755 index 0000000..4036edf Binary files /dev/null and b/0036-valid-sudoku/Animation/HashMap.mp4 differ diff --git a/0036-valid-sudoku/Article/0036-valid-sudoku.md b/0036-valid-sudoku/Article/0036-valid-sudoku.md new file mode 100755 index 0000000..e54fc38 --- /dev/null +++ b/0036-valid-sudoku/Article/0036-valid-sudoku.md @@ -0,0 +1,134 @@ +# LeetCode 第 36 号问题:有效的数独 + +> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode ]() 系列文章之一。 +> +> 同步博客: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 diff --git a/0036-valid-sudoku/Code/1.java b/0036-valid-sudoku/Code/1.java new file mode 100755 index 0000000..a41cbc1 --- /dev/null +++ b/0036-valid-sudoku/Code/1.java @@ -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; + } +} \ No newline at end of file