2.
3.
4.
5.
6.
7.
滑动窗口也是双指针
8.
9.前缀积 sum变量
10 前缀和hash表
当前累加和sum,counts是这样的数组的个数
12
13.
14.变位词
判断全为零
15.
判断数组全为零就是匹配了
hash存字母次数
优化
18.
19
21
24 三指针
26.
哈希表(Hash table,也叫散列表),是根据关键码值 (Key value)而直接进行访问的数据结构 。. 也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。. 这个映射函数叫做散列函数,存放记录的数组叫做散列表。. 这里的对应关系f称为散列函数,又称为哈希(Hash函数),采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表(Hash table)。
指针多复杂
HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。只有不允许重复的作用,而map有定位的作用。
HashSet 允许有 null 值。
HashSet 是无序的,即不会记录插入的顺序。
HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对 HashSet 的并发访问。
HashSet 实现了 Set 接口。
32.
双指针
特殊情况,双指针模板,数组当hash
class Solution {
public boolean isAlienSorted(String[] words, String order) {
int[] index = new int[26];
for (int i = 0; i < order.length(); ++i) {
index[order.charAt(i) - 'a'] = i;
}
for (int i = 1; i < words.length; i++) {
boolean valid = false;
for (int j = 0; j < words[i - 1].length() && j < words[i].length(); j++) {
int prev = index[words[i - 1].charAt(j) - 'a'];
int curr = index[words[i].charAt(j) - 'a'];
if (prev < curr) {
valid = true;
break;
} else if (prev > curr) {
return false;
}
}
if (!valid) {
/* 比较两个字符串的长度 */
if (words[i - 1].length() > words[i].length()) {
return false;
}
}
}
return true;
}
}
转化排序,特殊情况
特殊数据结构栈
遍历
代码逻辑,题的逻辑。
单调栈
双指针
数组来模拟
class MovingAverage {
/** Initialize your data structure here. */
private Queue<Integer> q;
private int size;
private int sum;
public MovingAverage(int s) {
size=s;
sum=0;
q=new LinkedList<>();
}
public double next(int val) {
if(q.size()==size){
int pull=q.poll();
q.add(val);
sum+=val;
sum-=pull;
}
else{
q.add(val);
sum+=val;
}
return (double)sum/q.size();
}
}
class MovingAverage {
/** Initialize your data structure here. */
private Queue<Integer> q;
private int size;
private int sum;
public MovingAverage(int s) {
size=s;
sum=0;
q=new LinkedList<>();
}
public double next(int val) {
q.add(val);
sum+=val;
if(q.size()>size){
sum-=q.poll();
}
return (double)sum/q.size();
}
}
class RecentCounter {
private Queue<Integer> times;
public RecentCounter() {
times=new LinkedList<>();
}
public int ping(int t) {
times.add(t);
while(times.peek()<t-3000)
times.poll();
return times.size();
}
}
队列模拟
层次遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class CBTInserter {
private TreeNode root;
private Queue<TreeNode> queue;
public CBTInserter(TreeNode root) {
this.root=root;
queue=new LinkedList<>();
queue.offer(root);
while(queue.peek().left!=null&&queue.peek().right!=null){
TreeNode nodes=queue.poll();
queue.offer(nodes.left);
queue.offer(nodes.right);
}
}
public int insert(int v) {
TreeNode parent=queue.peek();
TreeNode node = new TreeNode(v);
if(parent.left==null){
parent.left=node;
}
else {
parent.right=node;
queue.poll();
queue.offer(parent.right);
queue.offer(parent.left);
}
return parent.val;
}
public TreeNode get_root() {
return this.root;
}
}
44.
45
46
47
48
public class Codec {
private int i=0;
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if(root==null)return "#";
String leftStr = serialize(root.left);
String rightStr = serialize(root.right);
return String.valueOf(root.val) + "," + leftStr + "," + rightStr;
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
String[] nodeStrs = data.split(",");
return dfs(nodeStrs );
}
private TreeNode dfs(String[] strs ) {
String str = strs[i ];
i ++;
if (str.equals("#")) {
return null;
}
TreeNode node = new TreeNode(Integer.valueOf(str));
node.left = dfs(strs);
node.right = dfs(strs);
return node;
}
}
两种情况
50
51
52
class Solution {
TreeNode head = null;//全局变量
public void dfs(TreeNode node) {
//只是处理当前的一个节点的代码
if (node == null) return;
dfs(node.right);//先到最右边
node.right = head;,也是末尾,从尾到头不断链接
head = node;
dfs(node.left);
node.left = null;//把当前节点的左边去掉
}
public TreeNode increasingBST(TreeNode root) {
dfs(root);
return head;
}
}
54.
55.
57
58
59
60
class Solution {
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
Queue<int[]> maxHeap=new PriorityQueue<>((a,b)->(b[0]+b[1]-a[0]-a[1]));
for (int i = 0; i < Math.min(k, nums1.length); ++i) {
for (int j = 0; j < Math.min(k, nums2.length); ++j) {
if(maxHeap.size()>=k){
int[] root=maxHeap.peek();
if (root[0] + root[1] > nums1[i] + nums2[j]) {
maxHeap.poll();
maxHeap.add(new int[]{nums1[i],nums2[j]});
}
}else
maxHeap.offer(new int[] {nums1[i], nums2[j]});
}
}
List<List<Integer>> res=new ArrayList<>();
while (!maxHeap.isEmpty()){
int []val=maxHeap.poll();
ArrayList<Integer> aaa = new ArrayList<>();//最土的办法
aaa.add(val[0]);
aaa.add(val[1]);
res.add( aaa );
}
return res;
}
}
63.
64
69
mid指针
71
72
73.
75
76.
77
78
79
80
81
82.
84
85 dfs回溯
class Solution {
public List<String> generateParenthesis(int n) {
List<String> result=new LinkedList<>();
helper(n,n,"",result);
return result;
}
private void helper(int left, int right, String parenthesis,List<String> result) {
if(left<0||right<0||right<left)return;
if(right==0&&left==0)
result.add( parenthesis);
left--;
helper(left,right,parenthesis+"(",result);
left++;
right--;
helper(left,right,parenthesis+")",result);
right++;
}
}
class Solution {
public String[][] partition(String s) {
int n = s.length();
char[] arr = s.toCharArray();
// 预处理
boolean[][] dp = new boolean[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
dp[i][j] = true;
}
}
for (int i = n - 1; i >= 0; i--) {
for (int j = i + 1; j < n; j++) {
dp[i][j] = (arr[i] == arr[j] && dp[i + 1][j - 1]);
}
}
List<List<String>> res = new ArrayList<>();n x
List<String> path = new ArrayList<>();
dfs(res, path, s, dp, 0);
// List<List<String>> 转 String[][],这里不重要
String[][] ans = new String[res.size()][];
for (int i = 0; i < res.size(); i++) {
ans[i] = new String[res.get(i).size()];
for (int j = 0; j < ans[i].length; j++) {
ans[i][j] = res.get(i).get(j);
}
}
return ans;
}
public void dfs(List<List<String>> res, List<String> path, String s, boolean[][] dp, int pos) {
int n=s.length();
if (pos == n) {
res.add(new ArrayList<>(path));
return;
}
for (int i = pos; i < n; i++) {
// s[pos:i] (闭区间)是一个回文,所以递归搜索s[i+1, s.length()-1]
if (dp[pos][i]) {
path.add(s.substring(pos, i + 1));
dfs(res, path, s, dp, i + 1);
path.remove(path.size() - 1);
}
}
}
}
87
分两种情况来看
三种可能
定义
动态规划双指针,双指针可以用在各个地方
找f之间的关系
先找题目的规律
**
94
95
96
101