前段时间因为考试等懈怠了,重新开始做题。决定专门开一篇博客迭代记录了,不然文章散乱。
class Solution {
public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
int nvars = 0;
Map<String,Integer> variables = new HashMap<>();//讲字符串映射成数字
//遍历映射
int n = equations.size();
for (int i=0;i<n;i++){
if(!variables.containsKey(equations.get(i).get(0))){
variables.put(equations.get(i).get(0),nvars++);
}
if(!variables.containsKey(equations.get(i).get(1))){
variables.put(equations.get(i).get(1),nvars++);
}
}
List<Pair>[]edges=new List[nvars];
for(int i = 0; i<nvars; i++){
edges[i] = new ArrayList<Pair>();
}
for(int i = 0;i<n;i++){
int va = variables.get(equations.get(i).get(0));
int vb = variables.get(equations.get(i).get(1));
edges[va].add(new Pair(vb,values[i]));
edges[vb].add(new Pair(va,1.0/values[i]));
}
int queriesConnt = queries.size();
double[]ret = new double[queriesConnt];
for (int i=0;i<queriesConnt;i++){
List<String> query = queries.get(i);
double result = -1.0;
if(variables.containsKey(query.get(0)) && variables.containsKey(query.get(1))){
int ia = variables.get(query.get(0));
int ib = variables.get(query.get(1));
if(ia==ib){
result= 1.0;
}else{
Queue<Integer>points = new LinkedList<Integer>();
points.offer(ia);
double[]ratios = new double[nvars];
Arrays.fill(ratios,-1.0);
ratios[ia]=1.0;
while(!points.isEmpty()&& ratios[ib]<0){
int x= points.poll();
for(Pair pair :edges[x]){
int y =pair.index;
double val = pair.value;
if(ratios[y]<0){
ratios[y] =ratios[x]*val;
points.offer(y);
}
}
}
result=ratios[ib];
}
}
ret[i]=result;
}
return ret;
}
}
class Pair{
int index;
double value;
Pair(int index,double value){
this.index=index;
this.value=value;
}
}
2.200.岛屿数量
懒人终于来更新了。今天题目用深搜和广搜做,其实还可以用并查集(太晚了,下次研究),将网格堪称图,竖直/水平的1相连,扫描,为1时,进行深搜,标记为0。深搜次数为岛屿数量。深搜广搜意义差不多。
class Solution {
// void dfs(char[][]grid,int nv,int nh){
// int v = grid.length;
// int h = grid[0].length;
// if(nv < 0 || nh < 0 || nv >= v || nh >= h || grid[nv][nh] == '0'){
// return;
// }
// grid[nv][nh] = '0';
// dfs(grid,nv-1,nh);
// dfs(grid,nv+1,nh);
// dfs(grid,nv,nh-1);
// dfs(grid,nv,nh+1);
// }
public int numIslands(char[][] grid) {
// int v = grid.length;
// int h = grid[0].length;
// int ans = 0;
// for (int nv =0 ;nv
// for(int nh = 0;nh
// if(grid[nv][nh]=='1'){
// ans++;
// dfs(grid,nv,nh);
// }
// }
// }
// return ans;
// bfs
if(grid==null || grid.length ==0){
return 0;
}
int r,c,ans=0;
int x = grid.length,y=grid[0].length;
for(int i = 0;i<x;++i){
for(int j=0;j<y;++j){
if(grid[i][j]=='1'){
++ans;
grid[i][j]='0';
Queue<Integer> queue =new LinkedList();
queue.add(i * y + j);
while(!queue.isEmpty()){
int index = queue.remove();
r = index / y;
c = index % y;
if(r-1>=0 && grid[r-1][c]=='1'){
queue.add((r-1)*y+c);
grid[r-1][c]='0';
}
if(c-1>=0 && grid[r][c-1]=='1'){
queue.add(r*y+c-1);
grid[r][c-1]='0';
}
if(r+1<x && grid[r+1][c]=='1'){
queue.add((r+1)*y+c);
grid[r+1][c]='0';
}
if(c+1<y && grid[r][c+1]=='1'){
queue.add(r*y+c+1);
grid[r][c+1]='0';
}
}
}
}
}
return ans;
}
}
dfs的结果比较快。。。
增加并查集部分,考虑到本体情况,无需对划分几个部分做记录,访问到0时无需置为0,并查集已经记录。只要对往右往下进行连通计算
class Solution {
// 并查集-学习下并查集
class UnionFind {
private int[] parent;
private int count;
public UnionFind(char[][]grid){
int m =grid.length;
int n = grid[0].length;
count = 0;
parent = new int[m * n];
for(int i=0;i<m;i++){
for(int j =0;j<n;j++){
if(grid[i][j]=='1'){
parent[i * n + j] = i * n + j;
count++;
}
}
}
}
public int find(int x){
if (parent[x]!=x){
parent[x]=find(parent[x]);
}
return parent[x];
}
public void union(int x,int y){
int rootx = find(x);
int rooty = find(y);
if(rootx != rooty){
parent[rootx]=rooty;
--count;
}
}
public int getCount(){
return count;
}
}
public int numIslands(char[][] grid) {
if(grid == null || grid.length==0){
return 0;
}
int row=grid.length,col=grid[0].length;
UnionFind uf =new UnionFind(grid);
for(int i =0;i<row;++i){
for(int j=0;j<col;++j){
if(grid[i][j]=='1'){
// grid[i][j]='0';无需置为0,联通信息已有
int old = i *col +j;
if(i+1<row && grid[i+1][j]=='1'){
uf.union(old,(i+1)*col+j);
}
if(j+1<col && grid[i][j+1]=='1'){
uf.union(old,i*col+j+1);
}
}
}
}
return uf.getCount();
}
}
竟然还是dfs最快
3.130. 被围绕的区域
今天题目和上一题太像了,从题目可以知道,我们只要找到边界的O,再通过深搜或者广搜,将与之相连的标记,最后在遍历一遍地图,将标记的改回O,其余改为X就可以得到答案
class Solution {
int r,c;
int []dx={1,-1,0,0};
int []dy={0,0,1,-1};
public void solve(char[][] board) {
r = board.length;
c = board[0].length;
if(r ==0){
return;
}
Queue<int[]>queue =new LinkedList<>();
for(int i=0;i<r;i++){
if(board[i][0]=='O'){
queue.add(new int[]{i,0});
}
if(board[i][c-1]=='O'){
queue.add(new int[]{i,c-1});
}
}
for(int i=1;i<c-1;i++){
if(board[0][i]=='O'){
queue.add(new int[]{0,i});
}
if(board[r-1][i]=='O'){
queue.add(new int[]{r-1,i});
}
}
while(!queue.isEmpty()){
int[] tmp =queue.poll();
int x=tmp[0],y=tmp[1];
board[x][y]='a';
for(int i=0;i<4;i++){
int mx =x+dx[i],my=y+dy[i];
if(mx<0 ||mx>=r||my<0||my>=c||board[mx][my]!='O'){
continue;
}
queue.add(new int[]{mx,my});
}
}
// for(int i =0;i
// // 遍历上下列
// dfs(board,i,0);
// dfs(board,i,c-1);
// }
// for(int i =0;i
// // 遍历上下行
// dfs(board,0,i);
// dfs(board,r-1,i);
// }
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
if(board[i][j]=='a'){
board[i][j]='O';
}else if(board[i][j]=='O') {
board[i][j]='X';
}
}
}
}
// public void dfs(char[][]board,int x,int y){
// if(x<0 || x >= r || y<0 || y >=c || board[x][y] !='O'){
// return;
// }
// board[x][y]='a';
// dfs(board,x-1,y);
// dfs(board,x,y-1);
// dfs(board,x+1,y);
// dfs(board,x,y+1);
// }
}
class BrowserHistory {
private int pos =-1,top=-1;
private List<String>his;
public BrowserHistory(String homepage) {
his =new ArrayList<>();
visit(homepage);
}
public void visit(String url) {
pos++;
if(his.size()<=pos){
his.add(url);
}else{
his.set(pos,url);
}
top = pos;
}
public String back(int steps) {
if(steps>pos){
steps = pos;
}
pos -= steps;
return his.get(pos);
}
public String forward(int steps) {
steps = Math.min(steps,top-pos);
pos+=steps;
return his.get(pos);
}
}
/**
* Your BrowserHistory object will be instantiated and called as such:
* BrowserHistory obj = new BrowserHistory(homepage);
* obj.visit(url);
* String param_2 = obj.back(steps);
* String param_3 = obj.forward(steps);
*/
class ThroneInheritance {
Map<String,ArrayList<String>> map =new HashMap<>();
Set<String> set_dead = new HashSet<>();
String kingName;
public ThroneInheritance(String kingName) {
this.kingName = kingName;
map.put(kingName,new ArrayList<>());
}
public void birth(String parentName, String childName) {
if(map.containsKey(parentName)){
map.get(parentName).add(childName);
}else{
ArrayList tmp = new ArrayList<>();
tmp.add(childName);
map.put(parentName,tmp);
}
}
public void death(String name) {
set_dead.add(name);
}
public List<String> getInheritanceOrder() {
ArrayList<String> ans = new ArrayList<>();
if(!set_dead.contains(kingName)){
ans.add(kingName);
}
dfs(kingName,ans);
return ans;
}
private void dfs(String name,ArrayList<String> res){
if(!map.containsKey(name)){
return;
}
ArrayList<String> childs =map.get(name);
for(String c :childs){
if(!set_dead.contains(c)){
res.add(c);
}
dfs(c,res);
}
}
}
/**
* Your ThroneInheritance object will be instantiated and called as such:
* ThroneInheritance obj = new ThroneInheritance(kingName);
* obj.birth(parentName,childName);
* obj.death(name);
* List param_3 = obj.getInheritanceOrder();
*/
6. 1603. 设计停车系统
今日eas题目,明天不做设计题了
class ParkingSystem {
private int[] content = new int[3];
public ParkingSystem(int big, int medium, int small) {
content[0]=big;
content[1]=medium;
content[2]=small;
}
public boolean addCar(int carType) {
if(content[carType-1]>0){
content[carType-1]--;
return true;
}
return false;
}
}
/**
* Your ParkingSystem object will be instantiated and called as such:
* ParkingSystem obj = new ParkingSystem(big, medium, small);
* boolean param_1 = obj.addCar(carType);
*/
7.207. 课程表
今日拓扑排序题,使用深搜和广搜,新的专题,还挺难。
class Solution {
List<List<Integer>> edges;
int []visited;//0为未访问,1为正在访问,2为完成
boolean valid= true;
int[]indeg;//入度
public boolean canFinish(int numCourses, int[][] prerequisites) {
edges = new ArrayList<List<Integer>>();
for (int i =0;i<numCourses;++i){
edges.add(new ArrayList<Integer>());
}
indeg = new int[numCourses];
for (int[]info:prerequisites){
edges.get(info[1]).add(info[0]);
++indeg[info[0]];
}
Queue<Integer> queue =new LinkedList<Integer>();
for(int i=0;i<numCourses;++i){
if(indeg[i]==0){
queue.offer(i);
}
}
int visit = 0;
while(!queue.isEmpty()){
++visit;
int u = queue.poll();
for(int v:edges.get(u)){
--indeg[v];
if(indeg[v]==0){
queue.offer(v);
}
}
}
return visit==numCourses;
// edges = new ArrayList>();
// for (int i =0;i
// edges.add(new ArrayList());
// }
// visited = new int[numCourses];
// for (int[]info:prerequisites){
// edges.get(info[1]).add(info[0]);
// }
// for(int i=0;i
// if(visited[i]==0){
// dfs(i);
// }
// }
// return valid;
}
// public void dfs(int i){
// visited[i] = 1;
// for(int v:edges.get(i)){
// if(visited[v]==0){
// dfs(v);
// if(!valid){
// return;
// }
// }else if(visited[v]==1){
// valid =false;
// return;
// }
// }
// visited[i]=2;
// }
}
class Solution {
public String longestWord(String[] words) {
// String ans ="";
// Set set = new HashSet<>();
// for(String word:words){
// set.add(word);
// }
// for(String word:words){
// if(word.length()>ans.length() || word.length()==ans.length()&& word.compareTo(ans)<0){
// boolean flag =true;
// for(int i=1;i
// if(!set.contains(word.substring(0,i))){
// flag=false;
// break;
// }
// }
// if(flag)ans=word;
// }
// }
// return ans;
if(words==null || words.length==0) return "";
Arrays.sort(words);
String curr="",prev=" ";//注意次数pre有个空字符,用于curr.charAt(0)==prev.charAt(0)
int index=0;
for (int i=0;i<words.length;++i){
curr=words[i];
if((curr.startsWith(prev) && curr.length()==prev.length()+1)){
if(curr.length()>words[index].length()){
index=i;
}
prev =curr;
}else{
if(curr.length()==1) prev = curr;
else if(curr.charAt(0)==prev.charAt(0) && prev.length()>=curr.length() && curr.substring(0,curr.length()-1).equals(prev.substring(0,curr.length()-1))) prev = curr;
else prev = prev;
}
}
return words[index];
}
}
9. 设计循环队列
使用单链表,其实数组就行,数组注意使用mod操作就好
class Node{
public int value;
public Node next;
public Node(int value){
this.value=value;
this.next=null;
}
}
class MyCircularQueue {
private Node head,tail;
private int capacity;
private int count;
public MyCircularQueue(int k) {
this.capacity=k;
}
public boolean enQueue(int value) {
if(this.count==this.capacity){
return false;
}
Node node = new Node(value);
if(this.count==0){
head=tail=node;
}else{
tail.next=node;
tail = node;
}
this.count++;
return true;
}
public boolean deQueue() {
if(this.count==0){
return false;
}
this.head =this.head.next;
this.count--;
return true;
}
public int Front() {
if(this.count==0){
return -1;
}else{
return this.head.value;
}
}
public int Rear() {
if(this.count==0){
return -1;
}else{
return this.tail.value;
}
}
public boolean isEmpty() {
return this.count==0;
}
public boolean isFull() {
return this.count==this.capacity;
}
}
/**
* Your MyCircularQueue object will be instantiated and called as such:
* MyCircularQueue obj = new MyCircularQueue(k);
* boolean param_1 = obj.enQueue(value);
* boolean param_2 = obj.deQueue();
* int param_3 = obj.Front();
* int param_4 = obj.Rear();
* boolean param_5 = obj.isEmpty();
* boolean param_6 = obj.isFull();
*/
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> ans = new ArrayList<>();
int rows=matrix.length,cols=matrix[0].length;
if(matrix==null || rows==0||cols==0){
return ans;
}
boolean [][]visited =new boolean[rows][cols];
int row=0,col=0;
int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
int index=0;
for(int i=0;i<rows*cols;++i){
ans.add(matrix[row][col]);
visited[row][col]=true;
int newRow =row+directions[index][0];
int newCol = col+directions[index][1];
if(newRow<0 || newRow>=rows ||newCol<0 ||newCol>=cols || visited[newRow][newCol]){
index = (index+1)%4;
}
row += directions[index][0];
col += directions[index][1];
}
return ans;
}
}
class Solution {
public int uniquePaths(int m, int n) {
//排列组合
// int tmp =0;
// if(m>n){
// tmp=m;
// m=n;
// n=tmp;
// }
// long ans=1;
// for(int x =n, y=1;y
// ans = ans*x/y;
// }
// return (int)ans;
//动态规划1
// int dp[][]=new int[m][n];
// for(int i =0;i
// dp[i][0]=1;
// }
// for(int j=0;j
// dp[0][j]=1;
// }
// for(int i =1;i
// for(int j=1;j
// dp[i][j]=dp[i-1][j]+dp[i][j-1];
// }
// }
// return dp[m-1][n-1];
// 动规3
int dp[]=new int [m];
for (int i=0;i<n;i++){
dp[0]=1;
for(int j = 1;j<m;j++){
dp[j]=dp[j-1]+dp[j];
}
}
return dp[m-1];
}
}
12.57. 插入区间
模拟过程,三种情况,两种直接插入,一种需要合并,为了避免数组移动,使用List
class Solution {
public int[][] insert(int[][] intervals, int[] newInterval) {
if(intervals.length==0){
return new int[][]{newInterval};
}
// int m =intervals.length,n=intervals[0].length;
List<int[]> ansList = new ArrayList<>();
int left = newInterval[0],right = newInterval[1];
boolean flag =false;
for (int[]interval:intervals){
if(right<interval[0]){
if(!flag){
ansList.add(new int[]{left,right});
flag=true;
}
ansList.add(interval);
}else if(left>interval[1]){
ansList.add(interval);
}else{
left = Math.min(left,interval[0]);
right = Math.max(right,interval[1]);
}
}
if(!flag){
ansList.add(new int[]{left,right});
}
int [][]ans = new int[ansList.size()][2];
for(int i=0;i<ansList.size();++i){
ans[i]=ansList.get(i);
}
return ans;
}
}
class Solution {
public int[][] generateMatrix(int n) {
int num = n * n;
int [][]ans =new int [n][n];
int [][]directions ={{0,1},{1,0},{0,-1},{-1,0}};
int index=0;
int cur =1;
int row =0,col=0;
while(cur<=num){
ans[row][col]=cur;
cur++;
int newRow = row+directions[index][0], newcol =col+directions[index][1];
if(newRow<0||newRow>=n||newcol<0||newcol>=n||ans[newRow][newcol]!=0){
index = (index+1)%4;
}
row = row+directions[index][0];
col = col+directions[index][1];
}
return ans;
}
}
class Solution {
public boolean exist(char[][] board, String word) {
int m =board.length,n=board[0].length;
//剪枝效果明显
int []cnt1=new int[255];
int []cnt2=new int[255];
for(int i =0;i<word.length();i++){
cnt1[word.charAt(i)]++;
}
for(char[] tmp :board){
for(char s:tmp){
cnt2[s]++;
}
}
for(int i =0;i<cnt1.length;i++){
if(cnt1[i]>cnt2[i]){
return false;
}
}
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
if(board[i][j]==word.charAt(0)){
if(dfs(board,i,j,0,word)) return true;
}
}
}
return false;
}
boolean dfs(char[][]board,int i,int j,int k,String s){
if(k==s.length()){
return true;
}
if(i<0 || i>=board.length|| j<0||j>=board[0].length){
return false;
}
if(board[i][j]!=s.charAt(k)){
return false;
}
char tmp = board[i][j];
board[i][j]='0';
boolean flag = dfs(board,i,j+1,k+1,s) || dfs(board,i+1,j,k+1,s) || dfs(board,i-1,j,k+1,s) || dfs(board,i,j-1,k+1,s);
board[i][j]=tmp;//回溯
return flag;
}
}
15.69. x 的平方根
使用二分法或者牛顿法(使用零点逼近)
class Solution {
public int mySqrt(int x) {
//二分法
// int start =0,end=x,ans=-1;
// while(start <= end){
// int mid = start+(end-start)/2;
// if((long)mid*mid <= x){
// ans =mid;
// start = mid+1;
// }else{
// end= mid-1;
// }
// }
// return ans;
//牛顿法
if(x==0){
return 0;
}
double C=x ,x0=C;
while(true){
double xi =0.5 * (x0+C/x0);
if(Math.abs(xi-x0)<1e-7){
break;
}
x0=xi;
}
return (int)(x0);
}
}
16 82. 删除排序链表中的重复元素 II
其实昨天做了去除重复元素1,由于是升序链表所以就听简单的。本题要注意头指针可能被去除,所以增加一个指向头指针的节点。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head==null){
return head;
}
ListNode dummy = new ListNode();
dummy.next=head;
ListNode cur = dummy;
while(cur.next!=null && cur.next.next!=null){
if(cur.next.val==cur.next.next.val){
int x = cur.next.val;
while(cur.next!=null && cur.next.val==x){
ListNode tmp = cur.next;
cur.next=tmp.next;
tmp=null;
}
}else{
cur= cur.next;
}
}
return dummy.next;
}
}
题目 | 解题链接 | 说明 |
---|---|---|
题目-82. 删除排序链表中的重复元素 II | 题解-82. 删除排序链表中的重复元素 II | 注意头节点可能删除 |
61. 旋转链表 | 源码 | (自己写的有点蠢,绕半天,应该直接接上头才好) |
173. 二叉搜索树迭代器 | 题解 | (中序遍历) |
190. 颠倒二进制位 | 题解 | 颠倒就是数字的循环颠倒,灵活采用与运算符和移位操作 |
74. 搜索二维矩阵 | 题解 | 升序。然后二分,看了提交发现自己好蠢,不用新开辟一个数组,直接用matrix[mid/n][mid%n]取值更节省空间。这个BST解法太秀了 |
78. 子集,90. 子集 II | 子集,子集2 | 两题相似,使用回溯做,这个明天开始做专题,感觉不是很会,在子集2中注意连续重复时,就排除当个子集,回溯得记住要回。。。 |
88. 合并两个有序数组 | 题解 | 应该是个简单题,第一种方法用两个头指针和一个额外完成。第二种方法用两个尾指针完成。(好菜 |
7. 整数反转 | 题解 | 判断是否溢出 |
141. 环形链表 | 题解 | 判断有环,一种使用hashset直接判断有没有访问,另外一种采用龟兔赛跑,如果有环兔子会追上龟 |
1252. 奇数值单元格的数目 | 题解 | 最简单的方式是二维数组模拟遍历,第二种方法两个数组统计1的个数 |
1309. 解码字母到整数映射 | 题解 | 欸,暴力遍历,char转string竟然还错了半天 |
153. 寻找旋转排序数组中的最小值 | 题解 | 今天题目就很奇怪,怎么感觉是简单题,二分或者直接遍历就好(遇到转折就返回) |
179. 最大数 | 题解 | 重写比较器,直接转换为字符串之间比大小。 |
208. 实现 Trie (前缀树) | 题解 | 21.4.12。使用一个26长度数组和字母一一对应即可 |
198. 打家劫舍,213. 打家劫舍 II | 劫舍1,劫舍2 | 21.4.15,两题思路相同,动态规划,取dp[i-2]+nums[i]和dp[i-1]大者,劫舍2种情况,一个是0-n-1,另一种是1-n |
661. 图片平滑器 | 题解 | 暴力法,遍历了每个元素的周边八个元素 |
217. 存在重复元素 | 题解 | 排序或者用hashmap,其实用set最好 |
220. 存在重复元素 III | 题解 | 暴力超时,要用滑动窗口 |
26. 删除有序数组中的重复项 | 题解 | 4.17 双指针,已排序数组,所以元素相同就是连续的,所以用双指针记录,慢指针获得非重复数字 |
1323. 6 和 9 组成的最大数字 | 题解 | 4.19就很蠢,转成字符串,高位碰到6就转9,然后跳出 |
1822. 数组元素积的符号 | 题解 | 4.19判断负数个数 |
27. 移除元素 | 题解 | 4.19双指针 |
28. 实现 strStr() | 题解 | 4.20暴力,使用charAt和substring还是有区别 |
91. 解码方法 | 题解 | 4.20动规,关键还是找到转移方程,明天开始做动规 |
303. 区域和检索 - 数组不可变 | 题解 | 用一个数组处理前缀和,申请n+1的数组。便于求解,不用考虑0 |
1025. 除数博弈 | 题解 | 我i感觉简单题的动规也好难- |
剑指 Offer 42. 连续子数组的最大和 | 题解 | 4.23继续动规 |
面试题 17.16. 按摩师 | 题解 | 4.23明天继续动规 |
392. 判断子序列 | 题解 | 4.24明天继续动规,这题easy肯定是因为暴力能做!动规的递推还是难找== |
面试题 08.01. 三步问题 | 题解 | 4.26简单dp,母函数不好求,不然更快 |
938. 二叉搜索树的范围和 | 题解 | 4.27简单dfs |
338. 比特位计数 | 题解 | 用了最简单的方法,这个动规的逻辑使用了最高有效位还是很难可以想到 |
1734. 解码异或后的排列 | 题解 | 5.11这题还很考异或操作,首先是n个正整数排列,其次是n是奇数,还需要研究研究 |
877. 石子游戏 | 题解 | 5.12动规,转移方程dp[i][j]表示i到j之间两者的最大差值 |
131. 分割回文串 | 题解 | 5.13动规加回溯,可以在研究研究 |
12. 整数转罗马数字 | 题解 | 硬编码模拟,效率低 |
1442. 形成两个异或相等数组的三元组数目 | 题解 | 异或编码,注意公式计算 |
1738. 找出第 K 大的异或坐标值 | 题解 | 异或牛逼 |
692. 前K个高频单词 | 题解 | hashmap+排序,发现自己java语法还是很不熟,知道思路写不出来 |
525. 连续数组 | 题解 | 6.3前缀和的思想 |
203. 移除链表元素 | 题解 | 6.5简单题,遍历链表 |
剑指 Offer 58 - II. 左旋转字符串 | 题解 | 6.9切片操作 ,简单题 |
1869. 哪种连续子字符串更长 | 题解 | 6.9用了四个变量分别记录长度和最长的,简单题 |
1863. 找出所有子集的异或总和再求和 | 题解 | 6.12本题竟然是简单题哈哈哈,暴力用dfs比较好理解,遍历 2 n 2^n 2n次方,使用二进制代表较为晦涩,最后数学方法难懂 |
278. 第一个错误的版本 | 题解 | 6.13二分,简答题 |
374. 猜数字大小 | 题解 | 6.14和昨天一样的题型,简单题 |
852. 山脉数组的峰顶索引 | 题解 | 6.15简单题,直接遍历简单,可用二分 |
题目 | 解题链接 | 说明 |
---|---|---|
877. 石子游戏 | 题解 | 6.16动规,没明白上次的写法竟然过了== |
一个月没做题,感觉这个时间把控不对,从专题开始做
题目 | 解题链接 | 说明 |
---|---|---|
96. 不同的二叉搜索树 | 题解 | 7.20动规,这题有点巧妙 |
95. 不同的二叉搜索树 II | 题解 | 7.21和昨天那题方法完全不同,使用回溯 |
98.验证二叉搜索树 | 题解 | 7.22递归验证,可以用中序 |
99. 恢复二叉搜索树 | 题解 | 7.23中序遍历,存在逆序就记录交换 |
101. 对称二叉树 | 题解 | 7.26递归和迭代 |
102. 二叉树的层序遍历 | 题解 | 7.27BFS |
104. 二叉树的最大深度 | 题解 | 7.28昨天问题的简化版本 |
103. 二叉树的锯齿形层序遍历 | 题解 | 7.29层序遍历,加一个层级判断,奇数逆序 |
108. 将有序数组转换为二叉搜索树 | 题解 | 7.30递归,找到中间值作为根 |
105. 从前序与中序遍历序列构造二叉树 | 题解 | 7.31前序中序构建树,注意两个遍历特点,递归完成 |
106. 从中序与后序遍历序列构造二叉树 | 题解 | 8.4和上一题一样 |
107. 二叉树的层序遍历 II | 题解 | 8.6中序遍历BFS,逆序 |
109. 有序链表转换二叉搜索树 | 题解 | 8.11和108一个同类型 |
110. 平衡二叉树 | 题解 | 8.12简单题 |
113. 路径总和 II | 题解 | 8.13树的遍历,采用bfs,利用两个队列分别存储节点和值,利用map回溯路径,可以使用dfs更简单 |
114. 二叉树展开为链表 | 题解 | 8.14最简单是采用前序遍历,细究可以思考左子树的最右节点是右子树的头节点 |
116. 填充每个节点的下一个右侧节点指针 | 题解 | 8.15第一种层序遍历,第二种用next,分同父节点,第二种不同父节点 |
129. 求根节点到叶节点数字之和 | 题解 | 8.16DFS |
199. 二叉树的右视图 | 题解 | 8.17bfs,记录每层最后一个节点 |
222. 完全二叉树的节点个数 | 题解 | 8.18递归左右子树,直接加1,该方法可以继续优化 |
226. 翻转二叉树 | 题解 | 8.22翻转二叉树,递归,左右节点呼唤 |
题目 | 解题链接 | 说明 |
---|---|---|
11. 盛最多水的容器 | 题解 | 8.24使用双指针,向内逼近 |
35. 搜索插入位置 | 题解 | 8.29二分 |
31. 下一个排列 | 题解 | 8.31从后往前定位,找到前面比后面小的数字,交换并升序前面后面的序列 |
39. 组合总和 | 题解 | 9.3回溯,数组和target的题目还挺多的,做了忘= |
40. 组合总和 II | 题解 | 9.4昨天的小拓展,加了一个重复条件 |
15. 三数之和 | 题解 | 9.5三树之和,面试常见,先排序,双指针! |
36. 有效的数独 | 题解 | 9.6维护行、列、方格hashmap,注意方格的索引 |
33. 搜索旋转排序数组 | 题解 | 9.7使用二分 |
45. 跳跃游戏 II | 题解 | 9.8贪心法,前向遍历,这种题型应该挺常见的 |
46. 全排列 | 题解 | 9.9回溯,本方法已经出现很多次,需加强理解 |
73. 矩阵置零 | 题解 | 9.10使用标记数组或者标记变量 |
77. 组合 | 题解 | 9.11组合,还是回溯! |
47. 全排列 II | 题解 | 9.12全排列回溯,经典题目 |
66. 加一 | 题解 | 9.13末尾往上加,循环判断,及时return |
48. 旋转图像 | 题解 | 9.14旋转矩阵,观察规律 |
80. 删除有序数组中的重复项 II | 题解 | 9.15快慢指针 |
81. 搜索旋转排序数组 II | 题解 | 9.16二分,注意边界 |
118. 杨辉三角 | 题解 | 9.16就数学递推 |
134. 加油站 | 题解 | 9.17两层循环带走 |
119. 杨辉三角 II | 题解 | 9.18可以用1的方法,也可以简化递推,用一维数组 |
189. 旋转数组 | 题解 | 9.20常规使用额外数组,O(1)首先反转全部,再翻转前k个,再反转后n-k个 |
题目 | 解题链接 | 说明 |
---|---|---|
3. 无重复字符的最长子串 | 题解 | 9.22滑动窗口,这个一定要学会 |
5. 最长回文子串 | 题解 | 9.23经典题目,动规,拓展中心 |
6. Z 字形变换 | 题解 | 9.24按行寻找,按行索引 |
8. 字符串转换整数 (atoi) | 题解 | 9.26符合日常场景题,模拟过程,首先跳过空格,使用sign标记正负,在判断是否溢出 |
13. 罗马数字转整数 | 题解 | 9.27简单题遍历,使用Map编码最初的字符 |
22. 括号生成 | 题解 | 9.28递归,回溯 |
38. 外观数列 | 题解 | 9.29递归,双指针计数 |
43. 字符串相乘 | 题解 | 9.30应用题,模拟乘法竖式过程 |
49. 字母异位词分组 | 题解 | 10.1巧用map |
93. 复原 IP 地址 | 题解 | 10.3经典回溯,减枝 |
151. 翻转字符串里的单词 | 题解 | 10.8自带api方便,也可以用一个栈,或者自定义实现api |
165. 比较版本号 | 题解 | 10.14其实不是很难,自己绕进去了 |
168. Excel表列名称 | 题解 | 10.15相当于26进制,做一个偏移 |
171. Excel 表列序号 | 题解 | 10.16昨天的逆向 |
题目 | 解题链接 | 说明 |
---|---|---|
241. 为运算表达式设计优先级 | 题解 | 10.18使用分治 |
300. 最长递增子序列 | 题解 | 10.20简单判断 |
5. 最长回文子串 | 题解 | 10.21算复习把,中心拓展,马拉车不想看== |
22. 括号生成 | 题解 | 10.22回溯,复习了 |
55. 跳跃游戏 | 题解 | 10.24贪心法,每次更新最远能到的距离 |
53. 最大子序和 | 题解 | 10.24动规,维护pre= max(pre+num[i],num[i] |
45. 跳跃游戏 II | 题解 | 10.25贪心,动规,维护最远距离,当能达到最远距离时才更新步数 |
97. 交错字符串 | 题解 | 10.29动规,dp[i,j]=(dp[i-1,j]&&s1[i-1]==s3[i+j-1] )||(dp[i,i-1]&& s2[j-1]==s3[i+j-1]) |
213. 打家劫舍 II,212. 打家劫舍 | 题解 | 11.1打家劫舍经典动规 |
37. 打家劫舍 III | 题解 | 11.2树形dp,用dp记录两种状态 |
322. 零钱兑换 | 题解 | 11.2两成遍历,dp[i]=min[dp[i],dp[i-coins[j]]+1 |
343. 整数拆分 | 题解 | 11.3dp[i]=max(curMax,Math.max(ji-j,jdp[i-j)) |
357. 计算各个位数不同的数字个数 | 题解 | 11.4此题可以逆向作,dp为重复值,两种情况,1、dp[i-1]为已经重复了,所以第i位可以0-9。2、dp[i-1]未重复,所以(9pow(10,i-2)-dp[i-1])(i-1),前面为不重复的总值*任意i-1数字 |
1218. 最长定差子序列 | 题解 | 11.5 dp[v]=dp[v−d]+1.v为数组元素数字,d为difference |
72. 编辑距离 | 题解 | 11.22分为三种情况,dp[i][j]表示单词1的前i个字母和单词2的前j个字母的编辑距离 |
题目 | 解题链接 | 说明 |
---|---|---|
142. 环形链表 II | 题解 | 11.27哈希表或者快慢指针 |
133. 克隆图 | 题解 | 11.27本质需要遍历图,深搜,使用一个map记录访问过了 |
题目 | 解题链接 | 说明 |
---|---|---|
229. 求众数 II | 题解 | 12.1排序,统计次数,最简单是用哈希。 |
题目 | 解题链接 | 说明 |
---|---|---|
299. 猜数字游戏 | 题解 | 11.8每日一题,一层遍历,索引内容相同+1,用俩数组表示每个数字出现个数,取小的相加 |
2. 两数相加 | 题解 | 11.9每日一题,模拟链表相加过程 |
495. 提莫攻击 | 题解 | 11.10每日一题,一次遍历,直接比较duar和两者之差最小者 |
169. 多数元素 | 题解 | 11.11直接统计个数,或者排序取一半的都行 |
397. 整数替换 | 题解 | 11.19递归,进一步可以使用map,空间换时间 |
559. N 叉树的最大深度 | 题解 | 11.21递归,和二叉树一样 |
384. 打乱数组 | 题解 | 11.22random 随机取 |
859. 亲密字符串 | 题解 | 11.23 暴力解法,首先s和goal完全相同,需要有重复字母。否则,需要s[i]=goal[j] && s[j]=goal[i] |
423. 从英文中重建数字 | 题解 | 11.24有点傻逼,根据英文单词可以知道zwuxg只会出现在02468中,h(8.3),f(6,7),o(4,5),o(0,1,2,4),i(5,6,8,9),通过map统计词频就可以算出 |
700. 二叉搜索树中的搜索 | 题解 | 11.25根据二叉搜索树特性,如果小于节点的值就往左子树走否则往右子树走 |
519. 随机翻转矩阵 | 题解 | 11.26使用map映射 |
400. 第 N 位数字 | 题解 | 11.30重要定位,边界很容易错,么,根据位数其个数为x * 9*10 ^x-1 |
1446. 连续字符 | 题解 | 12.1一遍遍历统计 |
18. 四数之和 | 题解 | 12.1四树之和,排序双指针,剪枝 |
1005. K 次取反后最大化的数组和 | 题解 | 12.3排序,将负数变为正数,k剩余为偶数,数值不变,为基数减去最小值 |
383. 赎金信 | 题解 | 12.4统计英文词频 |
21. 合并两个有序链表 | 题解 | 12.4比大小合并 |
911. 在线选举 | 题解 | 12.11先预处理得到每个时刻的top,再二分查找t,查表 |
630. 课程表 III | 题解 | 12.14贪心,难= |
851. 喧闹和富有 | 题解 | 12.15 构造图和dfs |
1154. 一年中的第几天 | 题解 | 12.21硬编码每个月天数,闰年2月+1 |
1791. 找出星型图的中心节点 | 添加链接描述 | 12.23直接对比前两个点,,有个都出现的就是中心点 |
1705. 吃苹果的最大数目 | 题解 | 12.24贪心加最小堆(优先队列),先吃最快腐烂的 |
1609. 奇偶树 | 题解 | 12.25典型bfs,需要逐层遍历,以及奇偶判断 |
1078. Bigram 分词 | 题解 | 12.26直接分割遍历 |
825. 适龄的朋友 | 题解 | 12.27分析数学公式,排序,双指针找区间 |
1995. 统计特殊四元组 | 题解 | 12.29数据较小,可以直接枚举,或者使用map,存储nums[d]出现的个数,少一层循环;或者是存储nums[d]-nums[c]变为2重循环 |
1576. 替换所有的问号 | 题解 | 1.5使用3个字符循环 |
71. 简化路径 | 题解 | 1.6使用双端队列 |
1614. 括号的最大嵌套深度 | 题解 | 1.7统计连续左括号个数 |
89. 格雷编码 | 题解 | 1.8位运算不是很会 |
373. 查找和最小的 K 对数字 | 题解 | 1.14最小堆或者二分 |
1220. 统计元音字母序列的数目 | 题解 | 1.17动规,找到每个字母的前面可以是什么 |