Skip to content

Commit 3d7e20d

Browse files
committed
HOT100-简单题
1 parent 4a37a7a commit 3d7e20d

11 files changed

+564
-0
lines changed

leetcode_Java/DoneTitle.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1+
1. 两数之和
2+
20. 有效的括号
3+
21. 合并两个有序链表
4+
53. 最大子数组和
5+
70. 爬楼梯
16
94. 二叉树的中序遍历
27
101. 对称二叉树
38
102. 二叉树的层序遍历
49
104. 二叉树的最大深度
510
105. 从前序与中序遍历序列构造二叉树
611
114. 二叉树展开为链表
12+
121. 买卖股票的最佳时机
13+
136. 只出现一次的数字
14+
141. 环形链表
715
144. 二叉树的前序遍历
816
145. 二叉树的后序遍历
17+
155. 最小栈
18+
160. 相交链表
919
226. 翻转二叉树
1020
589. N叉树的前序遍历

leetcode_Java/Solution0001.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// 两数之和
2+
3+
4+
/*
5+
思路:
6+
1、中间数据使用HashMap存放,记录值和索引。结果数据使用整型数组存放
7+
2、输入的数组使用for循环遍历,通过目标值相减的方式获取输入数组中和HashMap中满足条件的两个整数,获取其索引存入结果数组
8+
*/
9+
class Solution {
10+
public int[] twoSum(int[] nums, int target) {
11+
HashMap<Integer, Integer> map = new HashMap<>();
12+
int[] res = new int[2];
13+
for (int i = 0; i < nums.length; i++) {
14+
if (map.containsKey(target - nums[i])) {
15+
res[0] = i;
16+
res[1] = map.get(target - nums[i]);
17+
return res;
18+
} else {
19+
map.put(nums[i], i);
20+
}
21+
}
22+
return res;
23+
}
24+
}

leetcode_Java/Solution0020.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// 有效的括号
2+
3+
4+
/*
5+
思路:
6+
1、括号有序,即使多层嵌套也必然至少有一对相邻有序出现,从内部逐层抵消
7+
2、使用while循环判断字符串的相邻有序对
8+
*/
9+
class Solution {
10+
public boolean isValid(String s) {
11+
while (s.contains("()") || s.contains("{}") || s.contains("[]")) {
12+
if (s.contains("()")) {
13+
s = s.replace("()", "");
14+
}
15+
if (s.contains("{}")) {
16+
s = s.replace("{}", "");
17+
}
18+
if ( s.contains("[]")) {
19+
s = s.replace("[]", "");
20+
}
21+
}
22+
return s.isEmpty();
23+
}
24+
}
25+
26+
27+
/*
28+
思路:
29+
1、使用HashMap存放括号对,方便映射获取
30+
2、由括号的顺序特点,使用栈存放左括号,以后进先出的方式与右括号抵消
31+
3、字符串使用for循环遍历处理每个字符,维护一个栈,碰到左括号就入栈,碰到右括号则取出栈顶元素,判断栈顶元素和右括号是否匹配
32+
4、栈为空或括号不匹配,则为false,否则true
33+
*/
34+
class Solution {
35+
public boolean isValid(String s) {
36+
HashMap<Character, Character> map = new HashMap<Character, Character>() {{
37+
put('(', ')');
38+
put('{', '}');
39+
put('[', ']');
40+
}};
41+
Stack<Character> stack = new Stack<>();
42+
for (int i = 0; i < s.length(); i++) {
43+
char c = s.charAt(i);
44+
if (map.containsKey(c)) {
45+
stack.push(c);
46+
} else if (stack.isEmpty() || map.get(stack.pop()) != c) {
47+
return false;
48+
}
49+
}
50+
return stack.isEmpty();
51+
}
52+
}

leetcode_Java/Solution0021.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// 合并两个有序链表
2+
3+
4+
/**
5+
* Definition for singly-linked list.
6+
* public class ListNode {
7+
* int val;
8+
* ListNode next;
9+
* ListNode() {}
10+
* ListNode(int val) { this.val = val; }
11+
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
12+
* }
13+
*/
14+
15+
16+
/*
17+
递归思路:
18+
1、终止条件:其中一个节点为空
19+
2、方法功能:入参两个节点,比较值的大小,返回值较小的节点
20+
3、递归逻辑:下一个有序节点同样可以通过调用这个方法得到,一次递归获得值较小的节点,返回给上一层拼接成链表,最后得到有序的链表
21+
*/
22+
class Solution {
23+
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
24+
if (list1 == null) {
25+
return list2;
26+
} else if (list2 == null) {
27+
return list1;
28+
} else if (list1.val < list2.val) {
29+
list1.next = mergeTwoLists(list1.next, list2);
30+
return list1;
31+
} else {
32+
list2.next = mergeTwoLists(list1, list2.next);
33+
return list2;
34+
}
35+
}
36+
}
37+
38+
39+
/*
40+
迭代思路:
41+
1、创建一个新结点,用于最后返回链表头
42+
2、使用pre指针,连接结点成链表
43+
3、使用while循环判断并连接两个链表值较小的节点,链表的节点被连接后,该链表指针指向下一个节点继续判断
44+
4、其中一个链表为空后循环结束,连接另一个不为空的链表的剩余部分
45+
*/
46+
class Solution {
47+
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
48+
ListNode head = new ListNode(-1);
49+
ListNode pre = head;
50+
while (list1 != null && list2 != null) {
51+
if (list1.val < list2.val) {
52+
pre.next = list1;
53+
list1 = list1.next;
54+
} else {
55+
pre.next = list2;
56+
list2 = list2.next;
57+
}
58+
pre = pre.next;
59+
}
60+
pre.next = list1 == null ? list2 : list1;
61+
return head.next;
62+
}
63+
}

leetcode_Java/Solution0053.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// 最大子数组和
2+
3+
4+
/*
5+
贪心思路:
6+
1、遍历数组,当前元素的 之前和大于0 时,则加上当前值得到当前和,这样累加值才会更大,否则将当前值赋给当前和
7+
2、当前和只是一个中间变量,记录过程中每个局部最大和。比较历史最大值 和 当前和,得到较大值
8+
*/
9+
class Solution {
10+
public int maxSubArray(int[] nums) {
11+
int res = nums[0];
12+
int sum = 0;
13+
for (int num : nums) {
14+
if (sum > 0) {
15+
sum += num;
16+
} else {
17+
sum = num;
18+
}
19+
res = Math.max(res, sum);
20+
}
21+
return res;
22+
}
23+
}
24+
25+
26+
/*
27+
贪心思路:
28+
1、核心思路都是判断以前一个元素结尾的子序列的最大值能不能给当前元素结尾的序列提供增益
29+
2、如果之前和为负数就不能提供增益,加上当前元素后会比当前元素小,因此通过比较大小就能获得当前和的最大值
30+
*/
31+
class Solution {
32+
public int maxSubArray(int[] nums) {
33+
int res = nums[0];
34+
int sum = 0;
35+
for (int num : nums) {
36+
sum = Math.max(sum + num, num);
37+
res = Math.max(res, sum);
38+
}
39+
return res;
40+
}
41+
}
42+
43+
44+
/*
45+
动态规划思路:
46+
1、dp[i]表示以i结尾子串的最大值
47+
2、初始条件:dp[0] = nums[0]
48+
3、状态转移方程:
49+
if (dp[i - 1] > 0) dp[i] = dp[i - 1] + nums[i];
50+
else dp[i] = nums[i];
51+
4、从dp数组中每个局部最大值获取全局最大值
52+
*/
53+
class Solution {
54+
public int maxSubArray(int[] nums) {
55+
int n = nums.length;
56+
int[] dp = new int[n];
57+
dp[0] = nums[0];
58+
for (int i = 1; i < n; i++) {
59+
if (dp[i - 1] > 0) {
60+
dp[i] = dp[i - 1] + nums[i];
61+
} else {
62+
dp[i] = nums[i];
63+
}
64+
}
65+
int res = dp[0];
66+
for (int i = 1; i < n; i++) {
67+
res = Math.max(res, dp[i]);
68+
}
69+
return res;
70+
}
71+
}

leetcode_Java/Solution0070.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// 爬楼梯
2+
3+
4+
/*
5+
递推思路:
6+
1、规律:1,2,3,5,8 后一个数是前两个数的和
7+
2、初始化两个值,根据规律逐渐推算出第n个数的值
8+
*/
9+
class Solution {
10+
public int climbStairs(int n) {
11+
int a = 1, b = 1;
12+
int temp;
13+
while (n > 1) {
14+
temp = b;
15+
b += a;
16+
a = temp;
17+
n -= 1;
18+
}
19+
return b;
20+
}
21+
}
22+
23+
24+
/*
25+
动态规划思路:
26+
1、dp[i]表示i阶楼梯的方法数量
27+
2、初始条件:dp[0] = dp[1] = 1
28+
3、状态转移方程:dp[i] = dp[i - 1] + dp[i - 2]
29+
*/
30+
class Solution {
31+
public int climbStairs(int n) {
32+
int[] dp = new int[n + 1];
33+
dp[0] = dp[1] = 1;
34+
for (int i = 2; i <= n; i++) {
35+
dp[i] = dp[i - 1] + dp[i - 2];
36+
}
37+
return dp[n];
38+
}
39+
}

leetcode_Java/Solution0121.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// 买卖股票的最佳时机
2+
3+
4+
/*
5+
动态规划思路:
6+
1、dp[i]表示前i+1天可获得的最大利润
7+
2、初始条件:dp[0] = 0,第1天的最大利润为0
8+
3、状态转移方程:dp[i] = Math.max(dp[i - 1], prices[i] - minPrice)
9+
*/
10+
class Solution {
11+
public int maxProfit(int[] prices) {
12+
int n = prices.length;
13+
int[] dp = new int[n];
14+
dp[0] = 0;
15+
int minPrice = prices[0];
16+
for (int i = 1; i < n; i++) {
17+
minPrice = Math.min(minPrice, prices[i]);
18+
dp[i] = Math.max(dp[i - 1], prices[i] - minPrice);
19+
}
20+
return dp[n - 1];
21+
}
22+
}
23+
24+
25+
/*
26+
思路:
27+
1、动态规划维护的dp数组,存放的每个元素只用一次就不需要了,因此可以直接用一个变量来表示利润最大值
28+
2、遍历列表,计算到当天为止的价格最小值、利润最大值
29+
*/
30+
class Solution {
31+
public int maxProfit(int[] prices) {
32+
int minPrice = 99999, maxProfit = 0;
33+
for (int price : prices) {
34+
minPrice = Math.min(minPrice, price);
35+
maxProfit = Math.max(maxProfit, price - minPrice);
36+
}
37+
return maxProfit;
38+
}
39+
}

leetcode_Java/Solution0136.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// 只出现一次的数字
2+
3+
4+
/*
5+
思路:使用HashMap记录每个数出现的次数,遍历HashMap查找只出现一次的数字
6+
*/
7+
class Solution {
8+
public int singleNumber(int[] nums) {
9+
HashMap<Integer, Integer> map = new HashMap<>();
10+
for (int num : nums) {
11+
int count = map.getOrDefault(num, 0);
12+
map.put(num, ++count);
13+
}
14+
for (int num : map.keySet()) {
15+
if (map.get(num) == 1) {
16+
return num;
17+
}
18+
}
19+
return -1;
20+
}
21+
}
22+
23+
24+
/*
25+
思路:使用列表存放数字。没有出现过则存入,出现过则移除,最后剩下一个只出现一次的数字
26+
*/
27+
class Solution {
28+
public int singleNumber(int[] nums) {
29+
List<Integer> list = new ArrayList<>();
30+
for (int num : nums) {
31+
Integer numObj = num;
32+
if (list.contains(numObj)) {
33+
list.remove(numObj);
34+
} else {
35+
list.add(numObj);
36+
}
37+
}
38+
return list.get(0);
39+
}
40+
}
41+
42+
43+
/*
44+
思路:
45+
既满足时间复杂度又满足空间复杂度,就要提到位运算中的异或运算 XOR,主要因为异或运算有以下几个特点:
46+
一个数和 0 做 XOR 运算等于本身:a⊕0 = a
47+
一个数和其本身做 XOR 运算等于 0:a⊕a = 0
48+
XOR 运算满足交换律和结合律:a⊕b⊕a = (a⊕a)⊕b = 0⊕b = b
49+
故而在以上的基础条件上,将所有数字按照顺序做异或运算,最后剩下的结果即为唯一的数字
50+
*/
51+
class Solution {
52+
public int singleNumber(int[] nums) {
53+
int res = 0;
54+
for (int num : nums) {
55+
res ^= num;
56+
}
57+
return res;
58+
}
59+
}

0 commit comments

Comments
 (0)