Skip to content

Commit fb2465e

Browse files
程序员吴师兄程序员吴师兄
程序员吴师兄
authored and
程序员吴师兄
committed
整理部分文件
1 parent 1a2d739 commit fb2465e

File tree

27 files changed

+1825
-21
lines changed

27 files changed

+1825
-21
lines changed

0001-Two-Sum/Animation/Animation.gif

252 KB
Loading

0001-Two-Sum/Article/0001-Two-Sum.md

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# LeetCode 第 1 号问题:两数之和
2+
3+
> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一。
4+
>
5+
> 同步博客:https://www.algomooc.com
6+
>
7+
8+
题目来源于 LeetCode 上第 1 号问题:两数之和。题目难度为 Easy,目前通过率为 45.8% 。
9+
10+
### 题目描述
11+
12+
给定一个整数数组 `nums` 和一个目标值 `target`,请你在该数组中找出和为目标值的那 **两个** 整数,并返回他们的数组下标。
13+
14+
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
15+
16+
**示例:**
17+
18+
```
19+
给定 nums = [2, 7, 11, 15], target = 9
20+
21+
因为 nums[0] + nums[1] = 2 + 7 = 9
22+
所以返回 [0, 1]
23+
```
24+
25+
### 题目解析
26+
27+
使用查找表来解决该问题。
28+
29+
设置一个 map 容器 record 用来记录元素的值与索引,然后遍历数组 nums。
30+
31+
* 每次遍历时使用临时变量 complement 用来保存目标值与当前值的差值
32+
* 在此次遍历中查找 record ,查看是否有与 complement 一致的值,如果查找成功则返回查找值的索引值与当前变量的值 i
33+
* 如果未找到,则在 record 保存该元素与索引值 i
34+
35+
### 动画描述
36+
37+
![](../Animation/animation.gif)
38+
39+
### 代码实现
40+
41+
```
42+
// 1. Two Sum
43+
// https://leetcode.com/problems/two-sum/description/
44+
// 时间复杂度:O(n)
45+
// 空间复杂度:O(n)
46+
class Solution {
47+
public:
48+
vector<int> twoSum(vector<int>& nums, int target) {
49+
unordered_map<int,int> record;
50+
for(int i = 0 ; i < nums.size() ; i ++){
51+
52+
int complement = target - nums[i];
53+
if(record.find(complement) != record.end()){
54+
int res[] = {i, record[complement]};
55+
return vector<int>(res, res + 2);
56+
}
57+
58+
record[nums[i]] = i;
59+
}
60+
}
61+
};
62+
63+
```
64+
65+
66+
67+
68+
69+
![](../../Pictures/qrcode.jpg)
305 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# LeetCode 第 2 号问题:两数相加
2+
3+
> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一。
4+
>
5+
> 同步博客:https://www.algomooc.com
6+
7+
题目来源于 LeetCode 上第 2 号问题:两数相加。题目难度为 Medium,目前通过率为 33.9% 。
8+
9+
### 题目描述
10+
11+
给出两个 **非空** 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 **逆序** 的方式存储的,并且它们的每个节点只能存储 **一位** 数字。
12+
13+
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
14+
15+
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
16+
17+
**示例:**
18+
19+
```
20+
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
21+
输出:7 -> 0 -> 8
22+
原因:342 + 465 = 807
23+
```
24+
25+
### 题目解析
26+
27+
设立一个表示进位的变量`carried`,建立一个新链表,把输入的两个链表从头往后同时处理,每两个相加,将结果加上`carried`后的值作为一个新节点到新链表后面。
28+
29+
### 动画描述
30+
31+
![](../Animation/animation.gif)
32+
33+
### 代码实现
34+
35+
```
36+
/// 时间复杂度: O(n)
37+
/// 空间复杂度: O(n)
38+
/**
39+
* Definition for singly-linked list.
40+
* public class ListNode {
41+
* int val;
42+
* ListNode next;
43+
* ListNode(int x) { val = x; }
44+
* }
45+
*/
46+
class Solution {
47+
public:
48+
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
49+
50+
ListNode *p1 = l1, *p2 = l2;
51+
ListNode *dummyHead = new ListNode(-1);
52+
ListNode* cur = dummyHead;
53+
int carried = 0;
54+
while(p1 || p2 ){
55+
int a = p1 ? p1->val : 0;
56+
int b = p2 ? p2->val : 0;
57+
cur->next = new ListNode((a + b + carried) % 10);
58+
carried = (a + b + carried) / 10;
59+
60+
cur = cur->next;
61+
p1 = p1 ? p1->next : NULL;
62+
p2 = p2 ? p2->next : NULL;
63+
}
64+
65+
cur->next = carried ? new ListNode(1) : NULL;
66+
ListNode* ret = dummyHead->next;
67+
delete dummyHead;
68+
return ret;
69+
}
70+
};
71+
72+
```
73+
74+
75+
76+
![](../../Pictures/qrcode.jpg)
77+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# LeetCode 第 3 号问题:无重复字符的最长子串
2+
3+
> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一。
4+
>
5+
> 同步博客:https://www.algomooc.com
6+
7+
题目来源于 LeetCode 上第 3 号问题:无重复字符的最长子串。题目难度为 Medium,目前通过率为 29.0% 。
8+
9+
### 题目描述
10+
11+
给定一个字符串,请你找出其中不含有重复字符的 **最长子串** 的长度。
12+
13+
**示例 1:**
14+
15+
```java
16+
输入: "abcabcbb"
17+
输出: 3
18+
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3
19+
```
20+
21+
### 题目解析
22+
23+
建立一个256位大小的整型数组 freg ,用来建立字符和其出现位置之间的映射。
24+
25+
维护一个滑动窗口,窗口内的都是没有重复的字符,去尽可能的扩大窗口的大小,窗口不停的向右滑动。
26+
27+
- (1)如果当前遍历到的字符从未出现过,那么直接扩大右边界;
28+
- (2)如果当前遍历到的字符出现过,则缩小窗口(左边索引向右移动),然后继续观察当前遍历到的字符;
29+
- (3)重复(1)(2),直到左边索引无法再移动;
30+
- (4)维护一个结果res,每次用出现过的窗口大小来更新结果 res,最后返回 res 获取结果。
31+
32+
### 动画描述
33+
34+
![动画描述](https://blog-1257126549.cos.ap-guangzhou.myqcloud.com/blog/20ahe.gif)
35+
36+
### 代码实现
37+
38+
```c++
39+
// 滑动窗口
40+
// 时间复杂度: O(len(s))
41+
// 空间复杂度: O(len(charset))
42+
class Solution {
43+
public:
44+
int lengthOfLongestSubstring(string s) {
45+
int freq[256] = {0};
46+
int l = 0, r = -1; //滑动窗口为s[l...r]
47+
int res = 0;
48+
// 整个循环从 l == 0; r == -1 这个空窗口开始
49+
// 到l == s.size(); r == s.size()-1 这个空窗口截止
50+
// 在每次循环里逐渐改变窗口, 维护freq, 并记录当前窗口中是否找到了一个新的最优值
51+
while(l < s.size()){
52+
if(r + 1 < s.size() && freq[s[r+1]] == 0){
53+
r++;
54+
freq[s[r]]++;
55+
}else { //r已经到头 || freq[s[r+1]] == 1
56+
freq[s[l]]--;
57+
l++;
58+
}
59+
res = max(res, r-l+1);
60+
}
61+
return res;
62+
}
63+
};
64+
```
65+
66+
![](../../Pictures/qrcode.jpg)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# LeetCode 第 9 号问题:回文数
2+
3+
> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一。
4+
>
5+
> 同步博客:https://www.algomooc.com
6+
7+
题目来源于 LeetCode 第 9 号问题:回文数。题目难度为 Easy,目前通过率为 56.0%。
8+
9+
## 题目描述
10+
11+
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
12+
13+
**示例 1:**
14+
15+
```
16+
输入: 121
17+
输出: true
18+
```
19+
20+
**示例 2:**
21+
22+
```
23+
输入: -121
24+
输出: false
25+
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
26+
```
27+
28+
**示例 3:**
29+
30+
```
31+
输入: 10
32+
输出: false
33+
解释: 从右向左读, 为 01 。因此它不是一个回文数。
34+
```
35+
36+
**进阶:**
37+
38+
你能不将整数转为字符串来解决这个问题吗?
39+
40+
41+
42+
## 题目解析
43+
44+
### 解法一:普通解法
45+
46+
最好理解的一种解法就是先将 **整数转为字符串** ,然后将字符串分割为数组,只需要循环数组的一半长度进行判断对应元素是否相等即可。
47+
48+
#### 动画描述
49+
50+
![](https://blog-1257126549.cos.ap-guangzhou.myqcloud.com/blog/ods8b.gif)
51+
52+
#### 代码实现
53+
54+
```java
55+
///简单粗暴,看看就行
56+
class Solution {
57+
public boolean isPalindrome(int x) {
58+
String reversedStr = (new StringBuilder(x + "")).reverse().toString();
59+
return (x + "").equals(reversedStr);
60+
}
61+
}
62+
```
63+
64+
65+
66+
### 解法二:进阶解法---数学解法
67+
68+
通过取整和取余操作获取整数中对应的数字进行比较。
69+
70+
举个例子:1221 这个数字。
71+
72+
- 通过计算 1221 / 1000, 得首位1
73+
- 通过计算 1221 % 10, 可得末位 1
74+
- 进行比较
75+
- 再将 22 取出来继续比较
76+
77+
#### 动画描述
78+
79+
![](https://blog-1257126549.cos.ap-guangzhou.myqcloud.com/blog/v3tkl.gif)
80+
81+
#### 代码实现
82+
83+
```java
84+
class Solution {
85+
public boolean isPalindrome(int x) {
86+
//边界判断
87+
if (x < 0) return false;
88+
int div = 1;
89+
//
90+
while (x / div >= 10) div *= 10;
91+
while (x > 0) {
92+
int left = x / div;
93+
int right = x % 10;
94+
if (left != right) return false;
95+
x = (x % div) / 10;
96+
div /= 100;
97+
}
98+
return true;
99+
}
100+
}
101+
```
102+
103+
104+
105+
### 解法三:进阶解法---巧妙解法
106+
107+
直观上来看待回文数的话,就感觉像是将数字进行对折后看能否一一对应。
108+
109+
所以这个解法的操作就是 **取出后半段数字进行翻转**
110+
111+
这里需要注意的一个点就是由于回文数的位数可奇可偶,所以当它的长度是偶数时,它对折过来应该是相等的;当它的长度是奇数时,那么它对折过来后,有一个的长度需要去掉一位数(除以 10 并取整)。
112+
113+
具体做法如下:
114+
115+
- 每次进行取余操作 ( %10),取出最低的数字:`y = x % 10`
116+
- 将最低的数字加到取出数的末尾:`revertNum = revertNum * 10 + y`
117+
- 每取一个最低位数字,x 都要自除以 10
118+
- 判断 `x` 是不是小于 `revertNum` ,当它小于的时候,说明数字已经对半或者过半了
119+
- 最后,判断奇偶数情况:如果是偶数的话,revertNum 和 x 相等;如果是奇数的话,最中间的数字就在revertNum 的最低位上,将它除以 10 以后应该和 x 相等。
120+
121+
#### 动画描述
122+
123+
![](https://blog-1257126549.cos.ap-guangzhou.myqcloud.com/blog/0siv7.png)
124+
125+
#### 代码实现
126+
127+
```java
128+
class Solution {
129+
public boolean isPalindrome(int x) {
130+
//思考:这里大家可以思考一下,为什么末尾为 0 就可以直接返回 false
131+
if (x < 0 || (x % 10 == 0 && x != 0)) return false;
132+
int revertedNumber = 0;
133+
while (x > revertedNumber) {
134+
revertedNumber = revertedNumber * 10 + x % 10;
135+
x /= 10;
136+
}
137+
return x == revertedNumber || x == revertedNumber / 10;
138+
}
139+
}
140+
```
141+
142+
![](../../Pictures/qrcode.jpg)

0 commit comments

Comments
 (0)