没有合适的资源?快使用搜索试试~ 我知道了~
leetcode1-300.docx
需积分: 0 0 下载量 192 浏览量
2024-01-25
08:49:57
上传
评论
收藏 1.37MB DOCX 举报
温馨提示
试读
321页
leetcode1-300.docx
资源推荐
资源详情
资源评论
//单调栈的典型用途是用于找到数组中下一个比自身大的元素 (the next greater element, NGE), 可以在一次遍
历就获得所有元素的NGE.
//Permutations题递归函数process()里传的是i; 其他的递归+回溯题目传的都是j
//删除链表中节点的常用方式
h1.next = h1.next.next; //the one after the h1 need to be removed
“粉红色”的题目为有没搞懂的地方.
最长公共子序列:dp
最长公共子串: 可用 dp
最长递增子序列:dp
链表题一定要记住, 出现了 cur.next.next, 就一定要同时判断 cur != null && cur.next != null.
其实回溯算法关键在于: 不合适就退回上一步
剪枝
回溯算法会应用「剪枝」技巧达到以加快搜索速度。有些时候,需要做一些预处理工作(例如排序)才能
达到剪枝的目的。预处理工作虽然也消耗时间,但能够剪枝节约的时间更多;
提示:剪枝是一种技巧,通常需要根据不同问题场景采用不同的剪枝策略,需要在做题的过程中不断总
结。
由于回溯问题本身时间复杂度就很高,所以能用空间换时间就尽量使用空间。
总结
做题的时候,建议 先画树形图 ,画图能帮助我们想清楚递归结构,想清楚如何剪枝。拿题目中的示例,
想一想人是怎么做的,一般这样下来,这棵递归树都不难画出。
在画图的过程中思考清楚:
分支如何产生;
题目需要的解在哪里?是在叶子节点、还是在非叶子节点、还是在从根节点到叶子节点的路径?
哪些搜索会产生不需要的解的?例如:产生重复是什么原因,如果在浅层就知道这个分支不能产生需要的
结果,应该提前剪枝,剪枝的条件是什么,代码怎么写?
题型三:字符串中的回溯问题
提示:字符串的问题的特殊之处在于,字符串的拼接生成新对象,因此在这一类问题上没有显示「回溯」
的过程,但是如果使用 StringBuilder 拼接字符串就另当别论。
在这里把它们单独作为一个题型,是希望朋友们能够注意到这个非常细节的地方。
如 17, 22
贪心:
Jump Game:
理解本质,nums[i] + i 的值才是决定是否能跳到下一个位置的关键因素,而不是单一的 nums[i] !!
能否跳到
i
位置取决于
i
之前所有位置的
nums[i] + i
的最大值
max
是否大于当前位置
i.
当我们不熟悉的时候,怎么想到用动态规划来解决这个问题呢?我们需要从问题本身出发,寻找一些有用
的信息,例如本题中:
(i, j)位置只能从(i - 1, j)和(i, j - 1)走到,这样的条件就是在告诉我们这里转移是「无后效性」的,f(i, j)和任
何的 f(i', j') (i' > i, j' > j)无关。
动态规划的题目分为两大类,一种是求最优解类,典型问题是背包问题,另一种就是计数类,比如这里的
统计方案数的问题,它们都存在一定的递推性质。前者的递推性质还有一个名字,叫做 「最优子结构」
——即当前问题的最优解取决于子问题的最优解,后者类似,当前问题的方案数取决于子问题的方案数。
所以在遇到求方案数的问题时,我们可以往动态规划的方向考虑。
通常如果我们察觉到了这两点要素,这个问题八成可以用动态规划来解决。读者可以多多练习,熟能生
巧。
快排:
1. 快排总结来说就是, 选取一个轴点 (在快排中是 arr[r]), 从 l 位置开始从前往后遍历, 小于轴点的
放在前面, 大于轴点的放在后面, 这样小于和大于区间的之间的自然就是等于区间 [less, more]
2. 而快排和荷兰国旗的区别就是:
a. 快排是选取 arr[r]作为轴点, 而 arr[r]是不属于大于区间的, 所以每次 partition 结束后都
要和 arr[more]做下交换; 而荷兰国旗直接选取 1 作为轴点.
b. 快排在 partition 过程外套了一个不断递归的架子; 而荷兰国旗只需要一次简单的
partition 过程即可.
我对滑动窗口的理解
先找到一个可行解,再优化这个可行解。
优化到不能优化,产生出一个可能的最优解。
继续找新的可行解,再优化这个可行解
……
在所有可能的最优解中,找出最优解。
1. Two Sum
Easy
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use
the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
class Solution {
public static int[] twoSum1(int[] arr, int target) {
if (arr == null || arr.length < 2) {
return new int[] { -1, -1 };
}
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
int value = target - arr[i];
if (map.containsKey(value)) {
return new int[] { map.get(value), i };
}
map.put(arr[i], i);
}
throw new IllegalArgumentException("No two sum Solution!");
}
public static int[] twoSum2(int[] arr, int target) {
if (arr == null || arr.length < 2) {
return new int[] { -1, -1 };
}
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
map.put(arr[i], i);
}
for (int i = 1; i < arr.length; i++) {
int value = target - arr[i];
if (map.containsKey(value) && map.get(value) != i) {
return new int[] { i, map.get(value) };
}
}
throw new IllegalArgumentException("No two sum Solution!");
}
}
2. Add Two Numbers
Medium
You are given two non-empty linked lists representing two non-negative integers. The digits are stored
in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a
linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example:
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if (l1 == null && l2 == null) {
return null;
}
ListNode head = null;
ListNode cur = null;
int carry = 0;
while (l1 != null || l2 != null) {
int num1 = l1 == null ? 0 : l1.val;
l1 = l1 == null ? null : l1.next;
int num2 = l2 == null ? 0: l2.val;
l2 = l2 == null ? null : l2.next;
int sum = num1 + num2 + carry;
carry = sum / 10;
if (head == null) {
head = cur = new ListNode(sum % 10);
} else {
cur.next = new ListNode(sum % 10);
cur = cur.next;
}
}
if (carry > 0) {
cur.next = new ListNode(carry); //注意, 必须要有这一步, 否则:
}
return head;
}
}
3. Longest Substring Without Repeating Characters
Medium
Given a string, find the length of the longest substring without repeating characters.
Example 1:
Input: "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) {
return 0;
}
int len = s.length();
int max = Integer.MIN_VALUE;
char[] c = s.toCharArray();
for (int i = 0; i < len; i++) {
HashSet<Character> set = new HashSet<>();
int count = 1;
set.add(c[i]);
for (int j = i + 1; j < len; j++) {
if (!set.contains(c[j])) {
set.add(c[j]);
count++;
} else {
break;
}
}
max = Math.max(max, count);
//i = i + 1; //注意, 这里不能再更新i了
}
return max;
}
}
4. Median of Two Sorted Arrays
Hard
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
class Solution {
public double findMedianSortedArrays(int[] arr1, int[] arr2) {
if (arr1.length == 0 && arr2.length == 0) {
return Double.MIN_VALUE;
}
int len1 = arr1.length;
int len2 = arr2.length;
int[] help = new int[len1 + len2];
Merge(arr1, arr2, help, len1, len2);
if (help.length % 2 == 1) {
return help[(help.length - 1) / 2];
剩余320页未读,继续阅读
资源评论
qq_40849626
- 粉丝: 6
- 资源: 15
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功