Topliked100(四)
3-Longest Substring Without Repeating Characters「滑动窗口」
Longest Substring Without Repeating Characters
给定一个字符串,找到最长不包含重复元素的子串长度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public int lengthOfLongestSubstring(String s) {
if(s.isEmpty())
return 0;
Map<Character, Integer> map = new HashMap<>();
int res = Integer.MIN_VALUE;
int start = 0, end = 0, count = 0;//count 记录重复字符的数量
while (end<s.length())
{
char cur = s.charAt(end);
map.put(cur, map.getOrDefault(cur, 0) + 1);
if(map.get(cur) > 1)
count++;
end++;
while (count>0)
{//有count个重复元素了,需要移动start使得[start, end)有效
char e = s.charAt(start);
if (map.get(e) > 1)
count--;
map.put(e, map.get(e) - 1);
start++;
}
//此时[start, end)是有效的
res = Math.max(res, end-start);
}
return res;
}
|
438-Find All Anagrams in a String「滑动窗口」
Find All Anagrams in a String
给定一个字符串s和p,找到s中所有的起始下标i,使得s从i开始的子串的字符全都在p中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
public List<Integer> findAnagrams(String s, String p) {
Map<Character, Integer> map = new HashMap<>();
List<Integer> res = new LinkedList<>();
for(char e: p.toCharArray())
{
map.put(e, map.getOrDefault(e, 0) +1);
}
int count = map.size(); // 字符种类数
int start = 0, end = 0;
while (end < s.length())
{
char cur = s.charAt(end);
if(map.containsKey(cur))
{
map.put(cur, map.get(cur) - 1);
if(map.get(cur)==0)
count--;
}
end++;
while (count==0)
{
char e = s.charAt(start);
if(map.containsKey(e))
{
if(map.get(e) == 0)
count++;
map.put(e, map.get(e) + 1);
}
if(end - start == p.length())
res.add(start);
start++;
}
}
return res;
}
|
543-Diameter of Binary Tree「DFS」
Diameter of Binary Tree
求一个二叉树的直径(最长路径从一个结点到另一个结点)。
显然,最长路径一定经过一个子树的根结点,可以转换为求树的深度的问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public class Solution543 {
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
private int max = 0;
public int diameterOfBinaryTree(TreeNode root) {
maxdepth(root);
return max;
}
private int maxdepth(TreeNode root)
{
if(root==null)
return 0;
else
{
int left = maxdepth(root.left);
int right = maxdepth(root.right);
max = Math.max(left + right, max);
return Math.max(left, right) + 1;
}
}
}
|
560-Subarray Sum Equals K[presum+哈希]
Subarray Sum Equals K
给定一个数组和一个整数k,找到连续子数组的数量,使得这个子数组和为k
这里计算和累积数组,因为sum(i, j) = sum(0, j) - sum(i)
。
用一个map保存累积和-频率。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public int subarraySum(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
int res = 0;
map.put(0, 1); //用于当sums==k的时候,下面的res+=1计算
int sums = 0;
for (int n: nums)
{
sums += n;
if(map.containsKey(sums - k))
//数组nums不一定全是正数,因此某些pre sum频率可能大于1
res += map.get(sums-k);
map.put(sums, map.getOrDefault(sums, 0) + 1);
}
return res;
}
|
647-Palindromic Substrings「回文串/技巧型」
Palindromic Substrings
给定一个字符串,找到所有回文子串的数量,起始和终止下标不一样的子串认为不是同一个。
采用一种比较技巧的方法,每次从中间向两边“扩张”,分为奇数和偶数两种情况。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
private int count = 0;
public int countSubstrings(String s) {
if(s.length()==0)
return 0;
for(int i = 0;i<s.length(); i++)
{
expand(s, i, i);
expand(s, i, i+1);
}
return count;
}
private void expand(String s, int left, int right)
{
while (left>=0&&right<s.length()&&s.charAt(left) == s.charAt(right))
{
count++;
left--;
right++;
}
}
|
739-Daily Temperatures「栈」
Daily Temperatures
题目大意给定一个数组,对每个元素找到需要走几步才能到达下一个大于当前值的元素。
用栈保存元素下标
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public int[] dailyTemperatures(int[] T) {
Stack<Integer> stack = new Stack<>();
int[] res = new int[T.length];
for(int i = 0;i<T.length; i++)
{
while (!stack.empty()&&T[stack.peek()]<T[i])
{
int top = stack.pop();
res[top] = i - top;
}
stack.push(i);
}
return res;
}
|
621-Task Scheduler「贪心」
Task Scheduler
给定一个任务序列,和一个n,要求相同任务至少间隔n个才行,问最终执行时间。
Input: tasks = [“A”,“A”,“A”,“B”,“B”,“B”], n = 2
Output: 8
Explanation: A -> B -> idle -> A -> B -> idle -> A -> B.
采用贪心的思想,首先找到任务序列之中的出现频率最高的,比如例子中的A,然后可以得到A–A–A,其中-表示空槽,这样,只需要每次把剩余元素顺序填空槽即可保证满足题意,如果剩余空槽,则表示填充不满,因此必须有空闲槽,否则表示空槽不够,因此总时间等于序列长度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public int leastInterval(char[] tasks, int n) {
int max = -1; // 最大频率
int maxCount = 0; // 有几个最大频率的,考虑AAABBBC这种,AB都是最大频率
int[] counter = new int[26];
for(char e : tasks)
{
counter[e-'A']++;
if(counter[e-'A']>max)
{
max = counter[e-'A'];
maxCount = 1;
}
else if(counter[e-'A']==max)
maxCount++;
}
int partCount = max - 1;
int emptySlots = partCount * (n-(maxCount-1));
int remainTasks = tasks.length - max * maxCount;
int idles = Math.max(0, emptySlots-remainTasks);
return tasks.length + idles;
}
|