目录

    • 797.回溯,dfs
    • 进制转换
    • 232栈,队列
    • 41
    • 13dfs
    • 7递归
    • 343,dp
    • 3,滑动窗口
      • 76,最小覆盖字串<滑动窗口>
      • 239,滑动窗口最大值
    • 59,螺旋矩阵Ⅱ
      • 螺旋矩阵Ⅰ
    • 小练习
      • 一,删除所有重复的节点
      • 二,求某一个数字在单条路径中出现最多的次数
      • 三,相乘后的最大结果
    • 50,Pow(x,n)
      • 372,超级次方
    • 20表示字符的字符串
    • 28对称的二叉树
    • 27二叉树的镜像
    • 26树的子结构
  • 152. 乘积最大子数组
  • Offer 19. 正则表达式匹配(dp)
  • Offer 35. 复杂链表的复制
    • Offer 41. 数据流中的中位数
    • Offer 36. 二叉搜索树与双向链表
    • 栈的压入、弹出序列
    • Offer 38. 字符串的排列
    • Offer 37. 序列化二叉树
    • 三数之和
    • Offer 32 - I. 从上到下打印二叉树
      • Offer 32 - II. 从上到下打印二叉树 II
      • Offer 32 - III. 从上到下打印二叉树 III
    • 字形变换
    • 451. 根据字符出现频率排序
    • 字典树
      • 211. 添加与搜索单词
    • 72. 编辑距离(dp)
    • 旋转数组
    • 二级目录

797.回溯,dfs

https://leetcode-cn.com/problems/all-paths-from-source-to-target/
分析:
从0号节点开始,进行dfs,并且将访问顶点加入path列表,如果当前节点为n-1号节点,将该列表加入result结果集。

代码如下(示例):

class Solution {List<List<Integer>> result;LinkedList<Integer> path;public List<List<Integer>> allPathsSourceTarget(int[][] graph) {result=new ArrayList<>();path=new LinkedList<>();dfs(graph,0);return result;}//num代表遍历到哪个节点拉//从0号节点开始,进行dfs,并且将访问顶点加入path列表,//如果当前节点为n-1号节点,将该列表加入result结果集。public void dfs(int[][] graph,int num){path.add(num);if(num==graph.length-1){result.add(new LinkedList<>(path));return;}for(int i=0;i<graph[num].length;i++){dfs(graph,graph[num][i]);path.removeLast();}}
}

进制转换

代码如下(示例):

//进制转换---》将字符串中的数转换成十进制,然后再转其他进制(2<=k<=36)
public class Solution {public static void main(String[] args) {System.out.println(transK("100",10,2));System.out.println(Integer.valueOf("100",2));}public static String transK(String str, int x, int y){//先将x进制对应的10进制得到,然后以10进制转其它进制int number=Integer.valueOf(str,x);char[] arr=new char[36];for(int i=0;i<10;i++){arr[i]=(char)('0'+i);}for(int i=10;i<36;i++){arr[i]=(char)('A'+i-10);}StringBuffer sb=new StringBuffer();while(number!=0){sb.append(arr[number%y]);number/=y;}//余数反转return sb.reverse().toString();}
}

232栈,队列

https://leetcode-cn.com/problems/implement-queue-using-stacks/submissions/

用栈实现队列

代码如下(示例):

class MyQueue {//savaStack来存储,positionStack来调换位置Stack<Integer> savaStack;Stack<Integer> positionStack;/** Initialize your data structure here. */public MyQueue() {savaStack=new Stack<>();positionStack=new Stack<>();}/** Push element x to the back of queue. */public void push(int x) {savaStack.push(x);}/** Removes the element from in front of queue and returns that element. */public int pop() {if(positionStack.isEmpty()){while(!savaStack.isEmpty()){positionStack.push(savaStack.pop());}}return positionStack.pop();}/** Get the front element. */public int peek() {if(positionStack.isEmpty()){while(!savaStack.isEmpty()){positionStack.push(savaStack.pop());}}return positionStack.peek();}/** Returns whether the queue is empty. */public boolean empty() {return savaStack.isEmpty()&&positionStack.isEmpty();}
}

用队列实现栈
https://leetcode-cn.com/problems/implement-stack-using-queues/submissions/

class MyStack {/**分析:队列先进先出,栈先进后出1,元素入栈可以创建saveQueue和positionQueue,saveQueue保存已有的数据,让每次加进来的数据加positionQueue中使得后进来的能成为队列头,然后将saveQueue中的元素拿出来加到positionQueue中,也就符合栈先进后出的特点,最后将saveQueue和positionQueue互换,此时saveQueue中的元素即为栈中的元素*/Queue<Integer> saveQueue;Queue<Integer> positionQueue;/** Initialize your data structure here. */public MyStack() {saveQueue=new LinkedList<>();positionQueue=new LinkedList<>();}/** Push element x onto stack. */public void push(int x) {positionQueue.add(x);while(!saveQueue.isEmpty()){positionQueue.add(saveQueue.poll());}Queue<Integer> temp=saveQueue;saveQueue=positionQueue;positionQueue=temp;}/** Removes the element on top of the stack and returns that element. */public int pop() {return saveQueue.poll();}/** Get the top element. */public int top() {return saveQueue.peek();}/** Returns whether the stack is empty. */public boolean empty() {return saveQueue.isEmpty()&&positionQueue.isEmpty();}
}

41

https://leetcode-cn.com/problems/first-missing-positive/

代码如下(示例):

class Solution {public int firstMissingPositive(int[] nums) {//由于返回第一个正整数,不包括0,所以length+1int[] newArr=new int[nums.length+1];//将数组元素添加到辅助数组中for(int x:nums){if(x>0&&x<newArr.length){newArr[x]=x;}}//遍历新数组,将缺少的数字返回for(int i=1;i<newArr.length;i++){if(newArr[i]!=i){return i;}}//刚好缺少最后一个正数,直接返回新数组长度return newArr.length;}
}

13dfs

https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/

代码如下(示例):

class Solution {//dfspublic int movingCount(int m, int n, int k) {boolean[][] visited=new boolean[m][n];return dfs(visited,m,n,k,0,0);}public int dfs(boolean[][] visited,int m,int n,int k,int i,int j){if(i>=m||j>=n||visited[i][j]||sums(i)+sums(j)>k){return 0;}visited[i][j]=true;return 1+dfs(visited,m,n,k,i+1,j)+dfs(visited,m,n,k,i,j+1);}//求位数为和public int sums(int num){int sum=0;while(num>0){sum+=num%10;num=num/10;}return sum;}
}

7递归

https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/


代码如下(示例):

class Solution {HashMap<Integer,Integer> infixmap=new HashMap<>(); //标记中序遍历int[] preorder;public TreeNode buildTree(int[] preorder, int[] inorder) {this.preorder=preorder;//将中序遍历的值和索引放在infixMap中,//方便获取左子树和右子数的数量和根节点的索引for(int i=0;i<inorder.length;i++){infixmap.put(inorder[i],i);}return recursion(0,0,preorder.length-1);}//前序遍历得到根节点,  中序左边界和右边界public TreeNode recursion(int pre_root,int leftEdge,int rightEdge){if(leftEdge>rightEdge) return null;//获取根节点TreeNode root=new TreeNode(preorder[pre_root]);//获取根节点的索引,方便获取左右子树的数量int rootIndex=infixmap.get(preorder[pre_root]);//左子树进行递归root.left=recursion(pre_root+1,leftEdge,rootIndex-1);//右子数进行递归//右子数根节点的索引=当前根节点索引+左子树数量+1root.right=recursion(pre_root+(rootIndex-  leftEdge)+1,rootIndex+1,rightEdge);return root;}
}

343,dp

https://leetcode-cn.com/problems/integer-break/submissions/


相同题目:https://leetcode-cn.com/problems/jian-sheng-zi-lcof/

代码如下(示例):

class Solution {public int integerBreak(int n) {int[] memeory=new int[n+1];memeory[1]=0;memeory[2]=1;for(int i=3;i<=n;i++){for(int j=1;j<=i-1;j++){memeory[i]=Math.max(memeory[i],Math.max(j*(i-j),j*memeory[i-j]));}}return memeory[n];}
}

链接:https://leetcode-cn.com/problems/jian-sheng-zi-ii-lcof/

找规律

n     乘积     组合
2       1       1 1
3       2       2
4       4       45       6       2 3
6       9       3 3
7       12      4 38       18      2 3 3
9       27      3 3 3
10      36      4 3 311      54      2 3 3 3
12      81      3 3 3 3
13      108     4 3 3 314      162     2 3 3 3 3
15      243     3 3 3 3 3
16      324     4 3 3 3 317      486     2 3 3 3 3 3
18      729     3 3 3 3 3 3
19      972     4 3 3 3 3 320      1458    2 3 3 3 3 3 3
21      2187    3 3 3 3 3 3 3
22      2916    4 3 3 3 3 3 323      4374    2 3 3 3 3 3 3 3
24      6561    3 3 3 3 3 3 3 3
25      8748    4 3 3 3 3 3 3 326      13122   2 3 3 3 3 3 3 3 3
27      19683   3 3 3 3 3 3 3 3 3
28      26244   4 3 3 3 3 3 3 3 329      39366   2 3 3 3 3 3 3 3 3 3
30      59049   3 3 3 3 3 3 3 3 3 3
……
//贪心算法//最优:3.把绳子尽可能切为多个长度为 3的片段,//留下的最后一段绳子的长度可能为0,1,2 三种情况。public int cuttingRope(int n) {if(n==2) return 1;if(n==3) return 2;long result=1;while(n>4){n-=3;result=(result*3)%1000000007;}//最后只剩下2,3,4这几种情况return (int)(result*n%1000000007);}

3,滑动窗口

3,无重复字符的最长字串
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

class Solution {//滑动窗口public int lengthOfLongestSubstring(String s) {if(s.length()==0){return 0;}Map<Character,Integer> map=new HashMap<>();int maxLength=0;int left=0;for(int i=0;i<s.length();i++){if(map.containsKey(s.charAt(i))){//遇到相同的,left移到相同元素的下一个位置然后接着开始left=Math.max(left,map.get(s.charAt(i)) + 1);}map.put(s.charAt(i),i);//最长字串长度maxLength=Math.max(maxLength,i-left+1);}return maxLength;}
}

76,最小覆盖字串<滑动窗口>

https://leetcode-cn.com/problems/minimum-window-substring/
官方题解:https://www.bilibili.com/video/av883276293/

1,当前缺失得字符种类

 //1,int missType = 0;//当前缺失得字符种类数/*** 输入字符串为 'ABC',则 map 初始为 { A: 1, B: 1, C: 1 },* 这些值是动态的,比如窗口新纳入一个 A,则 map["A"] 减 1。* map["A"] 为 0 代表不缺 A 了,A 字符找齐了。*/Map<Character, Integer> count = new HashMap<>();for (int i = 0; i < target.length(); i++) {char c = target.charAt(i);if (!count.containsKey(c)) {missType++; //添加一种 缺失字符种类}/*** Map.getOrDefault(Object key, V defaultValue)方法的作用是:*   当Map集合中有这个key时,就使用这个key值;*   如果没有就使用默认值defaultValue。*/count.put(c, count.getOrDefault(c, 0) + 1); //更新此目标字符需要的数量}

2,窗口的扩张
扩张窗口是为了纳入目标字符,右指针右移,先找到可行解——纳入了所有目标字符。
在还没找齐目标字符之前,左指针不动。因为如果此时它右移,可能丢失现有的目标字符。
什么时候停止扩张窗口?——当前窗口包含了所有目标字符。
此时再纳入字符,条件依然满足,但徒增子串长度。
此时应该优化可行解:收窄窗口,左指针右移。
3,窗口的收缩
保持条件满足的情况下,收缩窗口是优化可行解。当窗口不再包含所有目标字符,
即有目标字符丢失,就不再收缩。
此时应该扩张窗口,补充目标字符。
可见,为了找到最优解,一直做两种操作之一,直到窗口的右端到达边界。
2,3步代码

int left = 0;int right = 0;int minLen = s.length() + 1; //最小窗口长度int minStart = 0; //最小窗口的起点for (; right < s.length(); right++) {//2,char c = s.charAt(right);//右指针在扩张过程遇到了目标字符if (count.containsKey(c)) {count.put(c, count.get(c) - 1); //更新该目标字符仍需要的次数if (count.get(c) == 0) {missType--; //完成收集其中一种字符数量了}}//3,//扩张过程发现已经刚好达到目标字符串的要求,就要收缩优化,左指针向右移动//直到不满足要求,当窗口不再包含所有目标字符,即有目标字符丢失,就不再收缩while (missType == 0 && left <= right) {char leftChar = s.charAt(left);if (minLen > right - left + 1) {minLen = right - left + 1; //更新结果的最小窗口长度minStart = left; //更新最小窗口的字符串开始位置}if (count.containsKey(leftChar)) {count.put(leftChar, count.get(leftChar) + 1);if (count.get(leftChar) > 0) {missType++;//当出现了缺失的目标字符,缺失种类加一}}left++;//左指针向右移动,继续收缩}}return minLen > s.length() ?"" : s.substring(minStart, minStart + minLen);

题解:

class Solution {//滑动窗口public String minWindow(String s, String t) {//1,当前确实的字符种类int missType=0;//当前缺失的字符种类数Map<Character,Integer> count=new HashMap<>();for(int i=0;i<t.length();i++){char c=t.charAt(i);if(!count.containsKey(c)){missType++;//缺失的种类++}//当Map集合中有这个key时,就使用这个key值,如果没有就使用默认值defaultValue。count.put(c,count.getOrDefault(c,0)+1);}//2,窗口的扩张  3,窗口的收缩int left=0;  int right=0;//左右指针int minLen=s.length()+1;//最小窗口长度int minStart=0;//最小窗口的起点for(;right<s.length();right++){//2,窗口的扩张char c=s.charAt(right);//右指针在扩张过程中遇到了目标字符if(count.containsKey(c)){count.put(c,count.get(c)-1);//更新该目标字符仍需要的次数if(count.get(c)==0){missType--;//缺失的种类找到一个,减少一种}}//3,窗口的收缩,扩张过程发现已达到目标字符串的要求,就要收缩优化,左指针右移优化while(missType==0&&left<=right){char leftChar=s.charAt(left);if(minLen>right-left+1){minLen=right-left+1;//更新结果最小长度minStart=left;//更新最小窗口的字符串开始位置}if(count.containsKey(leftChar)){count.put(leftChar,count.get(leftChar)+1);if(count.get(leftChar)>0){missType++;//缺失的种类++}}left++;//左指针向右移动,继续收缩}}return minLen>s.length()?"":s.substring(minStart,minStart+minLen);}
}

239,滑动窗口最大值

https://leetcode-cn.com/problems/sliding-window-maximum/
暴力法:超时

class Solution {//暴力法public int[] maxSlidingWindow(int[] nums, int k) {ArrayList<Integer> list=maxInWindowArr(nums,k);int[] result = new int[list.size()];for(int i = 0;i<list.size();i++){ result[i] = list.get(i);}return result;}//滑动窗口最大值的集合public ArrayList<Integer> maxInWindowArr(int[] nums,int size){ArrayList<Integer> list=new ArrayList<>();if(size<1||nums.length<size) return list;int left=0;int right=size-1;while(right<nums.length){int maxInWindow=maxInWindow(left,right,nums);list.add(maxInWindow);left++;right++;}return list;}//滑动窗口中的最大值public int maxInWindow(int left,int right,int[] nums){int maxInWindow=nums[left];for(int i=left;i<=right;i++){if(maxInWindow<nums[i])   maxInWindow=nums[i];}return maxInWindow;}
}

单调队列:

class Solution {//单调队列public int[] maxSlidingWindow(int[] nums, int k) {int[] result=new int[nums.length-k+1];int size=k;int count=0;Deque<Integer> deque=new LinkedList<>();for(int i=0;i<nums.length;i++){//1,删除队列尾部,只要比加入的元素小就删除while(!deque.isEmpty()&&nums[deque.getLast()]<nums[i]){deque.pollLast();}//加入元素deque.addLast(i);//2,删除队列头部<不在窗口中的元素>while(!deque.isEmpty()&&deque.getFirst()<=i-size){deque.pollFirst();}//添加到结果集if(i>=size-1){result[count++]=nums[deque.getFirst()];}}return result;}
}

59,螺旋矩阵Ⅱ

https://leetcode-cn.com/problems/spiral-matrix-ii/

class Solution {//暴力法:模拟整个向内环绕的填入过程public int[][] generateMatrix(int n) {//矩阵初始化,边界初始化int[][] result=new int[n][n];int left=0;int right=result[0].length-1;int up=0;int down=result.length-1;//起始数字和终止数字int start=1;int target=n*n;//循环填入数字while(start<=target){//从左向右填充for(int i=left;i<=right;i++){result[up][i]=start;start++;}up++;//收缩边界//从上到下填充for(int i=up;i<=down;i++){result[i][right]=start;start++;}right--;//收缩边界//从右到左for(int i=right;i>=left;i--){result[down][i]=start;start++;}down--;//边界收缩//从下到上for(int i=down;i>=up;i--){result[i][left]=start;start++;}left++;//边界收缩}return result;}
}

螺旋矩阵Ⅰ

链接:https://leetcode-cn.com/problems/spiral-matrix/
题解及分析:

class Solution {//暴力法:模拟整个向内环绕的填入过程public List<Integer> spiralOrder(int[][] matrix) {List<Integer> result = new ArrayList<Integer>();if(matrix==null||matrix.length==0) return result;int left=0;int right=matrix[0].length-1;int up=0;int down=matrix.length-1;//终止数字int start=1;int target=matrix.length* matrix[0].length;//循环填入数字while(start<=target){//从左向右扫描,并加入到result中for(int i=left;i<=right&&start<=target;i++){result.add(matrix[up][i]);start++;}up++;//收缩边界//从上到下扫描for(int i=up;i<=down&&start<=target;i++){result.add(matrix[i][right]);start++;}right--;//收缩边界//从右到左扫描for(int i=right;i>=left&&start<=target;i--){result.add(matrix[down][i]);start++;}down--;//边界收缩//从下到上扫描for(int i=down;i>=up&&start<=target;i--){result.add(matrix[i][left]);start++;}left++;//边界收缩}return result;}
}

小练习

一,删除所有重复的节点


力扣:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/

 public ListNode deleteDuplicates(ListNode head) {ListNode dummy=new ListNode(-1,head);ListNode cur=dummy;while(cur.next!=null&&cur.next.next!=null){if(cur.next.val==cur.next.next.val){//保存这个相同的值int same=cur.next.val;while(cur.next!=null&&cur.next.val==same){cur.next=cur.next.next;}}else{//值不同cur=cur.next;}}return dummy.next;}

二,求某一个数字在单条路径中出现最多的次数


力扣:https://leetcode-cn.com/problems/longest-univalue-path/submissions/

class TreeNode{int val;TreeNode left;TreeNode right;TreeNode(int x){val=x;}public void setLeft(TreeNode left) {this.left = left;}public void setRight(TreeNode right) {this.right = right;}
}
public class Main {static int max = 0;public static void main(String[] args) {TreeNode root=new TreeNode(2);TreeNode leftroot=new TreeNode(3);TreeNode rightroot=new TreeNode(1);TreeNode leftrootleft=new TreeNode(3);TreeNode leftrootright=new TreeNode(1);TreeNode rightrootright=new TreeNode(1);root.setLeft(leftroot);root.setRight(rightroot);leftroot.setLeft(leftrootleft);leftroot.setRight(leftrootright);rightroot.setRight(rightrootright);System.out.println(longestUnivaluePath(root));}public static int longestUnivaluePath(TreeNode root) {if (root == null) return 0;max = 0;longestPath(root);return max+1;}/***找二叉树的最长相同节点路径数,对于每个节点来说,都可以将自己看作根节点,可以独立的看为一棵树,*(1)它的最长路径数要么是左子树的最长路径数,*(2)要么是右子树的最长路径数,*(3)要么就是左右子树的路径数相加(当然前提是左右子树的节点值和根节点值相等),这样用递归来解。* 求二叉树的最长相同节点个数:及就是在最长路径的基础上+1,还要去掉第三步左右子树的值跟根节点相等*///递归函数的功能其实就是从左子树和右子树中返回一个最大的同值路径public static int longestPath(TreeNode root){int leftLength=0;int rightLength=0;//(1)if(root.left!=null&&root.val==root.left.val){leftLength=1+longestPath(root.left);}else if(root.left!=null){longestPath(root.left);}//(2)if(root.right!=null&&root.val==root.right.val){rightLength=1+longestPath(root.right);}else if(root.right!=null){longestPath(root.right);}//(3)更新max,去掉左右子树相等的情况即可得到最长相同节点路径的个数if((leftLength+rightLength)>max&&root.left.val!=root.right.val){max=leftLength+rightLength;}return leftLength>rightLength?leftLength:rightLength;//每次返回最长的一条路}
}

三,相乘后的最大结果


public class Main {//DFSpublic static void main(String[] args) {int[] arr = new int[]{8,7,5,4,3,2};System.out.println(maxNum(arr));}static int res;static LinkedList<Integer> num1;static LinkedList<Integer> num2;public static int maxNum(int[] arr){//两个数首位已确定num1=new LinkedList<>();num2=new LinkedList<>();num1.addLast(arr[0]);num2.addLast(arr[1]);res=0;dfs(arr,2);//从第二个索引开始dfsreturn res;}private static void dfs(int[] arr, int index) {//两个三位数得到,将两个三位数相乘,每次将最大值进行更新if(index==arr.length){int maxSum1=0;int maxSum2=0;//拿到maxSum1for(int i:num1){maxSum1*=10;maxSum1+=i;}//拿到maxSum2for(int i:num2){maxSum2*=10;maxSum2+=i;}res=Math.max(res,maxSum1*maxSum2);return;}//DFSif(num1.size()==num2.size()){//如果两个数位数相同,则其都要进行dfs//先对num1dfsnum1.addLast(arr[index]);dfs(arr,index+1);num1.removeLast();//再对num2dfsnum2.addLast(arr[index]);dfs(arr,index+1);num2.removeLast();}else {if(num1.size()>num2.size()){num2.addLast(arr[index]);dfs(arr,index+1);num2.removeLast();}else{num1.addLast(arr[index]);dfs(arr,index+1);num1.removeLast();}}}
}

50,Pow(x,n)

https://leetcode-cn.com/problems/powx-n/
1,暴力法:超时

代码如下(示例):

//思路1:循环计算 n次 x相乘,时间复杂度O(n), 当n非常大时,效率低public static double myPow(double x, int n) {if(n==0) return 1.0;double result = 1;if (n >0) {for (int i = 0; i < n; i++) {result*=x;}} else {n=-n;for (int i = 0; i < n; i++) {result*=x;}result=1 / result;}return  result;}

2,快速幂–>实际上是分治思想
每次递归都会使得指数减少一半,因此递归的层数为 O(\log n)O(logn),
算法可以在很快的时间内得到结果。

代码:

 public double myPow(double x, int n) {if(n==Integer.MIN_VALUE)return (x==1||x==-1) ?1:0;else if(n==0) return 1;if(n<0) return myPow(1/x,-n);if(n%2==0) return myPow(x*x,n/2);else return x*myPow(x,n-1);    }

372,超级次方

https://leetcode-cn.com/problems/super-pow/

class Solution {//快速幂static int base=1337;//将数组元素放入栈中public int superPow(int a, int[] b) {Stack<Integer> stack=new Stack<>();int n=b.length;for(int i=0;i<n;i++){stack.push(b[i]);}return recursion(a,stack);}//缩小规模递归求解public int recursion(int a,Stack<Integer> stack){if(stack.isEmpty()) return 1;int last=stack.pop();int part1=myPower(a,last);int part2=myPower(recursion(a,stack),10);return part1*part2%base;}//a^kpublic int myPower(int a,int k){int res=1;a%=base;for(int i=0;i<k;i++){res*=a;res%=base;}return res;}
}

20表示字符的字符串

链接:https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/
代码及分析:

class Solution {public boolean isNumber(String s) {int index=0;//字符串索引int sLength=s.length();boolean hasNum=false;   boolean hasE=false;boolean hasSign=false;// +  -boolean hasDot=false;//  .//1,先处理开头空格,index后移while(index<sLength&&s.charAt(index)==' '){index++;}//2,遍历字符串,判断字符串是否表示数值while(index<sLength){/*(1)数字:  hasNum=true;index++ 到非数字 或者遍历到末尾位置if(index==n)  结束循环*/while(index<sLength&&s.charAt(index)>='0'&&s.charAt(index)<='9'){index++;hasNum=true;}if(index==sLength){break;}char c=s.charAt(index);/*(2)e/E:     e已经出现  或者e之前无数字,false  否则 hasE=true;并且将其他三个flag置为false,开始遍历e后面的新的一部分数字*/if(c=='e'||c=='E'){if(hasE||!hasNum){return false;}hasE=true;hasDot=false;   hasNum=false;    hasSign=false;}else if(c=='+'||c=='-'){/*(3)+/-:     如果已经出现过+/- 或者已经出现过数字或者已经出现过'.',返回flase;否则令hasSign = true*/if(hasSign||hasDot||hasNum){return false;}hasSign=true;}else if(c=='.'){/*(4).        如果已经出现过'.'或者已经出现过'e'或'E',返回false;否则令hasDot = true*/if(hasDot||hasE){return false;}hasDot=true;}else if(c==' '){break;/*(5)空         如果到末尾的空格了,结束循环;但也有可能是字符串中间的空格,在循环外继续处理*/}else{/*(6)其他情况返回false*/return false;}index++;}//3,处理空格,index相应的后移while(index<sLength&&s.charAt(index)==' '){index++;}//4,if(index==sLength) 遍历到了末尾;    但还要满足hasNum=true;//因为如果字符串全是符号而没有数字是不行的,而且e后面没有数字不行,但没有符号可以return hasNum&&index==sLength;}
}

28对称的二叉树

链接:https://leetcode-cn.com/problems/dui-cheng-de-er-cha-shu-lcof/
分析:

代码:

class Solution {public boolean isSymmetric(TreeNode root) {if(root==null){return true;}return symmetry(root.left,root.right);}public boolean symmetry(TreeNode leftNode, TreeNode rightNode){//如果左右节点都为空,就对称if(leftNode==null&&rightNode==null) return true;//如果左右节点其中一个为空,或者左边节点的值与对称位置的值不相等,就不对称if(leftNode==null||rightNode==null||leftNode.val!=rightNode.val) return false;return symmetry(leftNode.left,rightNode.right)&&symmetry(leftNode.right,rightNode.left);}
}

27二叉树的镜像

链接:https://leetcode-cn.com/problems/er-cha-shu-de-jing-xiang-lcof/
代码:

//根据二叉树镜像的定义,考虑递归遍历(dfs)二叉树,交换每个节点的左 / 右子节点,即可生成二叉树的镜像。
class Solution {//递归public TreeNode mirrorTree(TreeNode root) {if(root==null){return null;}TreeNode leftNode=mirrorTree(root.right);TreeNode rightNode=mirrorTree(root.left);root.left=leftNode;root.right=rightNode;return root;}
}

26树的子结构

链接:https://leetcode-cn.com/problems/shu-de-zi-jie-gou-lcof/
代码及分析:

class Solution {//我们只需要从根节点开始判断,通过递归的方式比较他的每一个子节点即可public boolean isSubStructure(TreeNode A, TreeNode B) {//边界值判断,如果A B有一个为空,就返回falseif(A==null||B==null){return false;}//B不光有可能是A的子结构,也有可能是A左子树的子结构或者右子树的子结构,//所以如果从根节点判断B不是A的子结构,还要继续判断B是不是A左子树的子结构和右子树的子结构return isSubStructure1(A,B)||isSubStructure(A.left,B)||isSubStructure(A.right,B);}//判断B是不是A的子结构public boolean isSubStructure1(TreeNode A, TreeNode B){//如果B为空,说明B访问完了,确定是A的子结构if(B==null){return true;}//如果B不为空,A为空,或者两个节点值不同,说明B不是A的子节点if(A==null||A.val!=B.val){return false;}//当前节点判断完,换要判断左右子节点return isSubStructure1(A.left,B.left)&&isSubStructure1(A.right,B.right);}
}

152. 乘积最大子数组

链接:https://leetcode-cn.com/problems/maximum-product-subarray/
错误:

分析及题解:

class Solution {/* dp:(1)遍历数组时计算当前最大值,不断更新(2)令imax为当前最大值,则当前最大值为 imax = max(imax * nums[i], nums[i])由于存在负数,那么会导致最大的变最小的,最小的变最大的。因此还需要维护当前最小值imin,imin = min(imin * nums[i], nums[i])(3)当负数出现时则imax与imin进行交换再进行下一步计算*/public int maxProduct(int[] nums) {int max=Integer.MIN_VALUE;//结果最大值   int imax=1;  int  imin=1;for(int i=0;i<nums.length;i++){//(3)if(nums[i]<0){int temp=imax;imax=imin;imin=temp;}//(1)    (2)imax=Math.max(imax*nums[i],nums[i]);imin=Math.min(imin*nums[i],nums[i]);//更新maxmax=Math.max(max,imax);}return max;}
}

Offer 19. 正则表达式匹配(dp)

链接:https://leetcode-cn.com/problems/zheng-ze-biao-da-shi-pi-pei-lcof/
分析:

代码:

class Solution {//dppublic boolean isMatch(String A, String B) {int n = A.length();int m = B.length();boolean[][] f = new boolean[n + 1][m + 1];for(int i=0;i<=n;i++){for(int j=0;j<=m;j++){if(j == 0){//如果B为空正则, A为空正则 0==0 返回true; 否则返回falsef[i][j] = i == 0;}else{//B不为空正则if (B.charAt(j - 1) != '*') {//(1)B的最后一个字符是正常字符 || B的最后一个字符是.if (i > 0 && (A.charAt(i - 1) == B.charAt(j - 1) || B.charAt(j - 1) == '.')){f[i][j] = f[i - 1][j - 1];}}else{//(2)如果B的最后一个字符是*它代表 B[m-2]=c可以重复0次或多次,它们是一个整体 c*//1,if (i >= 1 && j >= 2 && (A.charAt(i - 1) == B.charAt(j - 2) || B.charAt(j - 2) == '.')) {f[i][j] |= f[i - 1][j];}//2,  A[i-1]是0个cif (j >= 2) {f[i][j] |= f[i][j - 2];}}}}}return f[n][m];}
}

Offer 35. 复杂链表的复制

链接:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/
分析:

代码及分析:

class Solution {public Node copyRandomList(Node head) {if(head==null) return null;Node cur=head;// 1,复制各节点,并建立 “原节点 -> 新节点” 的 Map 映射Map<Node,Node> map=new HashMap<>();while(cur!=null){map.put(cur,new Node(cur.val));cur=cur.next;}cur=head;//2,构建新链表的 next 和 random 指向while(cur!=null){map.get(cur).next=map.get(cur.next);map.get(cur).random=map.get(cur.random);cur=cur.next;}//3,返回新链表的头节点return map.get(head);}
}

Offer 41. 数据流中的中位数

链接:https://leetcode-cn.com/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof/
分析及代码 小顶堆,大顶堆

class MedianFinder {/*1,输入的时候将数字分为两半,小的一半放在大根堆small中,大的一半放在小根堆的big中。2,输入的同时保证两堆的大小之差不超过一,如果超过,则将数量多的堆弹出堆顶元素放到另一个堆中。3,取中位数的时候,奇数返回数量多的堆顶元素;偶数返回两堆的堆顶平均数即可。*//** initialize your data structure here. */Queue<Integer> big, small;int count;  //数字数量public MedianFinder() {big = new PriorityQueue<>(); // 小顶堆,保存较大的一半small = new PriorityQueue<>((x, y) -> (y - x)); // 大顶堆,保存较小的一半count=0;}public void addNum(int num) {//1,if(small.isEmpty()){small.add(num);count++;return;}if(num<=small.peek()){small.add(num);count++;}else{big.add(num);count++;}//2,if(small.size()-big.size()==2){big.add(small.poll());}if(big.size()-small.size()==2){small.add(big.poll());}}public double findMedian() {//3,if(count%2!=0){if(small.size()>big.size()){return small.peek();}else{return big.peek();}     }else{return (small.peek() + big.peek()) * 0.5;}}
}

Offer 36. 二叉搜索树与双向链表

链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/
分析:

分析及代码

 //中序遍历递归
class Solution {//记录头结点private Node head = null;//记录遍历当前节点的前一个节点,用来把当前节点和前一个节点给串起来的private Node pre = null;public Node treeToDoublyList(Node root) {if(root==null) return root;inorder(root);//2,上面将链表各节点进行了双向连接,下面将链表的首尾连接起来head.left=pre;pre.right=head;return head;}//二叉树的中序遍历private void inorder(Node root) {if(root==null) return;//边界条件的判断//先遍历左子节点inorder(root.left);//1,将链表各节点进行双向连接if (pre == null) {//当前节点是头节点head = root;} else {//串起来的结果就是前一个节点pre的right指向当前节点,//然后当前节点的left指向前一个节点prepre.right = root;}root.left = pre;//前一个节点和当前节点串起来之后,就让前一个节点指向当前节点,向后遍历pre = root;//最后在遍历右子节点inorder(root.right);}
}

栈的压入、弹出序列

链接:https://leetcode-cn.com/problems/zhan-de-ya-ru-dan-chu-xu-lie-lcof/
分析及代码

class Solution {//入栈操作: 按照压栈序列的顺序执行。//出栈操作: 每次入栈后,循环判断 “栈顶元素 == 弹出序列的当前元素” 是否成立,将符合弹出序列顺序的栈顶元素全部弹出。public boolean validateStackSequences(int[] pushed, int[] popped) {Stack<Integer> stack=new Stack<>();int i=0;for(int num:pushed){stack.push(num);//入栈while(!stack.isEmpty()&&popped[i]==stack.peek()){stack.pop();i++;}}return stack.isEmpty();}
}

Offer 38. 字符串的排列

链接:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/submissions/
分析及代码:

class Solution {/*dfs:当前固定位 x1,剪枝:若 c[i] 在 Set​ 中,代表其是重复字符,因此 “剪枝” ;2,将 c[i] 加入 Set​ ,以便之后遇到重复字符时剪枝;3,固定字符: 将字符 c[i] 和 c[x] 交换,即固定 c[i] 为当前位字符;4,开启下层递归: 调用 dfs(x + 1) ,即开始固定第 x + 1 个字符;5,还原交换: 将字符 c[i] 和 c[x] 交换(还原之前的交换);*/List<String> res = new LinkedList<>();char[] c;public String[] permutation(String s) {c = s.toCharArray();dfs(0);return res.toArray(new String[res.size()]);}//从当前位置进行dfspublic void dfs(int x){if(x==c.length-1){res.add(String.valueOf(c));//添加一种排列方案return;}HashSet<Character> set = new HashSet<>();for(int i=x;i<c.length;i++){//1,如果重复就剪枝if(set.contains(c[i])) continue;//2,set.add(c[i]);//3,交换,将c[i]固定在第x位swap(i,x);//4,固定第x+1位dfs(x+1);//5,恢复交换swap(i,x);}}//交换两个位置的值public void swap(int a,int b){char temp=c[a];c[a]=c[b];c[b]=temp;}
}

Offer 37. 序列化二叉树

链接:https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/
分析及代码:

 /*
通常使用的前序、中序、后序、层序遍历记录的二叉树的信息不完整,即唯一的输出序列可能对应着多种二叉树可能性。
题目要求的 序列化 和 反序列化 是 可逆操作。因此,序列化的字符串应携带完整的二叉树信息 。*/
public class Codec {/*借助队列,对二叉树做层序遍历,并将越过叶节点的 null 也打印出来。1,特例处理:若 root 为空,则直接返回空列表 "[]" ;2,初始化:队列 queue (包含根节点 root );序列化列表 res ;3,层序遍历:当 queue 为空时跳出;节点出队列,记为 node ;若 node 不为空:(1)打印字符串 node.val (2) 将左、右子节点加入 queue ;否则(若 node 为空):打印字符串 "null" ;4,返回值: 拼接列表,用 ',' 隔开,首尾添加中括号;*/public String serialize(TreeNode root) {//1,if(root == null) return "[]";//2,StringBuilder res = new StringBuilder("[");Queue<TreeNode> queue = new LinkedList<>();queue.add(root);//3,while(!queue.isEmpty()) {TreeNode node = queue.poll();if(node != null) {res.append(node.val + ",");queue.add(node.left);queue.add(node.right);}else res.append("null,");}//4,res.deleteCharAt(res.length() - 1);res.append("]");return res.toString();}/*利用队列按层构建二叉树,借助一个指针i指向节点 node 的左、右子节点,每构建一个 node 的左、右子节点,指针i 就向右移动1位。1,特例处理:若 data 为空,直接返回 null2,初始化:序列化列表 vals (先去掉首尾中括号,再用逗号隔开),指针 i = 1 ,根节点 root (值为 vals[0] ),队列 queue(包含 root );3,按层构建: 当 queue 为空时跳出;节点出队,记为 node ;构建 node 的左子节点:node.left 的值为 vals[i] ,并将 node.left 入队;执行 i += 1 ;构建 node 的右子节点:node.left 的值为 vals[i] ,并将 node.left 入队;执行 i += 1 ;4,返回值: 返回根节点 root 即可;*/public TreeNode deserialize(String data) {//1,if(data.equals("[]")) return null;//2,String[] vals = data.substring(1, data.length() - 1).split(",");TreeNode root = new TreeNode(Integer.parseInt(vals[0]));Queue<TreeNode> queue = new LinkedList<>();queue.add(root);int i = 1;//3,while(!queue.isEmpty()) {TreeNode node = queue.poll();if(!vals[i].equals("null")) {node.left = new TreeNode(Integer.parseInt(vals[i]));queue.add(node.left);}i++;if(!vals[i].equals("null")) {node.right = new TreeNode(Integer.parseInt(vals[i]));queue.add(node.right);}i++;}//4,return root;}
}

三数之和

链接:https://leetcode-cn.com/problems/3sum/
分析及代码:

class Solution {/*双指针法思路:固定3个指针中最左(最小)数字的指针 k,双指针 i,j 分设在数组索引 (k, len(nums))两端,通过双指针交替向中间移动,记录对于每个固定指针 k 的所有满足 nums[k] + nums[i] + nums[j] == 0 的 i,j 组合:*/public List<List<Integer>> threeSum(int[] nums) {/*1,当 nums[k] > 0 时直接break跳出:因为 nums[j] >= nums[i] >= nums[k] > 0,即3个数字都大于0,在此固定指针 k 之后不可能再找到结果了。2,当 k > 0且nums[k] == nums[k - 1]时即跳过此元素nums[k]:因为已经将 nums[k - 1] 的所有组合加入到结果中,本次双指针搜索只会得到重复组合。3,i,j 分设在数组索引 (k, len(nums))(k,len(nums)) 两端,当i < j时循环计算s = nums[k] + nums[i] + nums[j],并按照以下规则执行双指针移动:当s < 0时,i += 1并跳过所有重复的nums[i];当s > 0时,j -= 1并跳过所有重复的nums[j];当s == 0时,记录组合[k, i, j]至res,执行i += 1和j -= 1并跳过所有重复的nums[i]和nums[j],防止记录到重复组合。*/Arrays.sort(nums);List<List<Integer>> res = new ArrayList<>();for(int k=0;k<nums.length-2;k++){//1.if(nums[k]>0) break;//2,if(k>0&&nums[k]==nums[k-1]) continue;//3,int i=k+1; int j=nums.length-1;while(i<j){int sum=nums[k]+nums[i]+nums[j];if(sum<0){while(i<j&&nums[i]==nums[++i]);}else if(sum>0){while(i<j&&nums[j]==nums[--j]);}else{res.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j])));while(i<j&&nums[i]==nums[++i]);while(i<j&&nums[j]==nums[--j]);}}}return res;}
}

Offer 32 - I. 从上到下打印二叉树

链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/

class Solution {/*BFS 循环: 当队列 queue 为空时跳出;1,出队: 队首元素出队,记为 node;2,打印: 将 node.val 添加至res 尾部;3,添加子节点: 若 node 的左(右)子节点不为空,则将左(右)子节点加入队列 queue ;*/public int[] levelOrder(TreeNode root) {if(root==null) return new int[0];Queue<TreeNode> queue=new LinkedList<>(){{add(root);} };ArrayList<Integer> list=new ArrayList<>();while(!queue.isEmpty()){//1,TreeNode node=queue.poll();//2,list.add(node.val);//3,if(node.left!=null) queue.add(node.left);if(node.right!=null) queue.add(node.right);}int[] res=new int[list.size()];for(int i=0;i<list.size();i++)res[i]=list.get(i);return res;}
}

Offer 32 - II. 从上到下打印二叉树 II

链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/

class Solution {/*BFS 循环: 当队列 queue 为空时跳出;1,新建一个临时列表 tmp ,用于存储当前层打印结果;2,当前层打印循环: 循环次数为当前层节点数(即队列 queue 长度);出队: 队首元素出队,记为 node;打印: 将 node.val 添加至 tmp 尾部;添加子节点: 若 node 的左(右)子节点不为空,则将左(右)子节点加入队列 queue ;3,将当前层结果 tmp 添加入 res 。*/public List<List<Integer>> levelOrder(TreeNode root) {Queue<TreeNode> queue=new LinkedList<>();List<List<Integer>> res=new ArrayList<>();if(root!=null) queue.add(root);while(!queue.isEmpty()){//1,List<Integer> temp=new ArrayList<>();//2,for(int i=queue.size();i>0;i--){TreeNode node=queue.poll();temp.add(node.val);if(node.left!=null) queue.add(node.left);if(node.right!=null) queue.add(node.right);}res.add(temp);}return res;}
}

Offer 32 - III. 从上到下打印二叉树 III

链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/

class Solution {public List<List<Integer>> levelOrder(TreeNode root) {Queue<TreeNode> queue=new LinkedList<>();List<List<Integer>> res=new ArrayList<>();if(root!=null) queue.add(root);int count=0;while(!queue.isEmpty()){//1,List<Integer> temp=new ArrayList<>();//2,for(int i=queue.size();i>0;i--){TreeNode node=queue.poll();temp.add(node.val);if(node.left!=null) queue.add(node.left);if(node.right!=null) queue.add(node.right);}count++;if(count%2==0){//如果count是偶数就反转单链表Collections.reverse(temp);}res.add(temp);}return res;}
}

字形变换

链接:https://leetcode-cn.com/problems/zigzag-conversion/

class Solution {/*算法流程: 按顺序遍历字符串 s;1,res[i] += c: 把每个字符 c 填入对应行res[i];2,i += flag: 更新当前字符 c 对应的行索引;3,flag = - flag: 在达到 ZZ 字形转折点时,执行反向。*/public String convert(String s, int numRows) {if(numRows<2) return s;List<StringBuilder> rows=new ArrayList<>();//几行for(int i=0;i<numRows;i++) rows.add(new StringBuilder());int i=0; int flag=-1;for(char c:s.toCharArray()){rows.get(i).append(c);if(i==0||i==numRows-1) flag=-flag;i+=flag;}StringBuilder res=new StringBuilder();for(StringBuilder row:rows) res.append(row);return res.toString();}
}

451. 根据字符出现频率排序

链接:https://leetcode-cn.com/problems/sort-characters-by-frequency/
分析及代码:

class Solution {/*1.使用哈希表记录每个字符出现的频率2.再将列表中的字符按照频率降序排序。3.遍历顺序为字符按照频率递减的顺序。对于每个字符,将该字符按照出现频率拼接到排序后的字符串*/public String frequencySort(String s) {//1Map<Character,Integer> map=new HashMap<>();int frequency=0;for(int i=0;i<s.length();i++){char c=s.charAt(i);frequency=map.getOrDefault(c,0)+1;map.put(c,frequency);}//2List<Character> list=new ArrayList<>(map.keySet());Collections.sort(list,(a,b)->map.get(b)-map.get(a));//3StringBuilder sb=new StringBuilder();for(int i=0;i<list.size();i++){char c=list.get(i);frequency=map.get(c);for(int j=0;j<frequency;j++){sb.append(c);}}return sb.toString();}
}

字典树

链接:https://leetcode-cn.com/problems/implement-trie-prefix-tree/
前缀树的3个基本性质:
1,根节点不包含字符,除根节点外每一个节点都只包含一个字符。
2,从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3,每个节点的所有子节点包含的字符都不相同。

通常字典树的查询时间复杂度是O(logL),L是字符串的长度。
字典树(tries树):
对于单词查询这种,还是用字典树比较好,但也是有前提的,空间大小允许,字典树的空间相比较hash还是比较浪费的,毕竟hash可以用bit数组。
那么在空间要求不那么严格的情况下,字典树的效率不一定比hash弱,它支持动态查询,比如apple,当用户输入到appl时,字典树此刻的查询位置可以就到达l这个位置,那么我在输入e时,光查询e就可以了(更何况如果我们直接用字母的ASCII作下标肯定会更快)!字典树它并不用等待你完全输入完毕后才查询。
208. 实现 Trie (前缀树)
分析及代码:

class Trie {private Trie[] children;private boolean isEnd;public Trie() {children=new Trie[26];isEnd=false;}/*从字典树的根开始,插入字符串。对当前字符对应的子节点,有两种情况:(1)子节点存在。沿着指针移动到子节点,继续处理下一个字符。(2)子节点不存在。创建一个新的子节点,记录在children 数组的对应位置上,然后沿着指针移动到子节点,继续搜索下一个字符。重复以上步骤,直到处理字符串的最后一个字符,然后将当前节点标记为字符串的结尾。*/public void insert(String word) {Trie node=this;for(int i=0;i<word.length();i++){char ch=word.charAt(i);int index=ch-'a';if(node.children[index]==null){node.children[index]=new Trie();}node=node.children[index];}node.isEnd=true;}public boolean search(String word) {Trie node=searchPrefix(word);return node!=null&&node.isEnd;}public boolean startsWith(String prefix) {return searchPrefix(prefix)!=null;}/*我们从字典树的根开始,查找前缀。对于当前字符对应的子节点,有两种情况:(1)子节点存在。沿着指针移动到子节点,继续搜索下一个字符。(2)子节点不存在。说明字典树中不包含该前缀,返回空指针。重复以上步骤,直到返回空指针或搜索完前缀的最后一个字符。若搜索到了前缀的末尾,就说明字典树中存在该前缀。此外,若前缀末尾对应节点的isEnd 为真,则说明字典树中存在该字符串。*/private Trie searchPrefix(String prefix){Trie node=this;for(int i=0;i<prefix.length();i++){char ch=prefix.charAt(i);int index=ch-'a';if(node.children[index]==null){return null;}node=node.children[index];}return node;}
}

211. 添加与搜索单词

链接:https://leetcode-cn.com/problems/design-add-and-search-words-data-structure/
分析及代码:

class WordDictionary {private Trie root;public WordDictionary() {root=new Trie();}public static void main(String[] args) {WordDictionary wordDictionary = new WordDictionary();wordDictionary.addWord("bad");wordDictionary.addWord("dad");wordDictionary.addWord("mad");System.out.println(wordDictionary.search("pad")); //falseSystem.out.println(wordDictionary.search("bad")); //trueSystem.out.println(wordDictionary.search(".ad")); //trueSystem.out.println(wordDictionary.search("b..")); //true;}public void addWord(String word) {root.insert(word);}public boolean search(String word) {return dfs(word,0,root);}/*对于搜索单词,从字典树的根结点开始搜索。由于待搜索的单词可能包含点号,因此在搜索过程中需要考虑点号(1)如果当前字符是字母,则判断当前字符对应的子结点是否存在,如果子结点存在,则移动到子结点,继续搜索下一个字符,如果子结点不存在则说明单词不存在,返回false;(2)如果当前字符是点号,由于点号可以表示任何字母,因此需要对当前结点的所有非空子结点继续搜索下一个字符。重复上述步骤,直到返回false或搜索完给定单词的最后一个字符。如果搜索完给定的单词的最后一个字符,则当搜索到的最后一个结点的isEnd 为true 时,给定的单词存在。特别地,当搜索到点号时,只要存在一个非空子结点可以搜索到给定的单词,即返回true。*/private boolean dfs(String word,int index,Trie node){if(index==word.length()){return node.isEnd();}char ch=word.charAt(index);if(Character.isLetter(ch)){int childrenIndex=ch-'a';Trie child=node.getChildren()[childrenIndex];if(child!=null&&dfs(word,index+1,child)){return true;}}else{for(int i=0;i<26;i++){Trie child=node.getChildren()[i];if(child!=null&&dfs(word,index+1,child)){return true;}}}return false;}
}
class Trie {private Trie[] children;private boolean isEnd;public Trie() {children=new Trie[26];isEnd=false;}public void insert(String word) {Trie node=this;for(int i=0;i<word.length();i++){char ch=word.charAt(i);int index=ch-'a';if(node.children[index]==null){node.children[index]=new Trie();}node=node.children[index];}node.isEnd=true;}public Trie[] getChildren(){return children;}public boolean isEnd(){return isEnd;}
}

72. 编辑距离(dp)

链接:https://leetcode-cn.com/problems/edit-distance/

dp[i][j] 代表 word1 到 i 位置转换成 word2 到 j 位置需要最少步数,所以,

当 word1[i] == word2[j],dp[i][j] = dp[i-1][j-1];

当 word1[i] != word2[j],dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1

其中,dp[i-1][j-1] 表示替换操作,dp[i-1][j] 表示删除操作,dp[i][j-1] 表示插入操作。
分析及代码:

class Solution {//dp//dp[i][j] 代表 word1 到 i 位置转换成 word2 到 j 位置需要最少步数public int minDistance(String word1, String word2) {int L1=word1.length();int L2=word2.length();int[][] dp=new int[L1+1][L2+1];//第一列for(int i=1;i<=L1;i++) dp[i][0]=dp[i-1][0]+1;//第一行for(int j=1;j<=L2;j++) dp[0][j]=dp[0][j-1]+1;for(int i=1;i<=L1;i++){for(int j=1;j<=L2;j++){//如果元素相同if(word1.charAt(i-1)==word2.charAt(j-1)){dp[i][j]=dp[i-1][j-1];}else{dp[i][j]=Math.min(Math.min(dp[i-1][j-1],dp[i][j-1]),dp[i-1][j])+1;}}}return dp[L1][L2];}
}

旋转数组

链接:https://leetcode-cn.com/problems/rotate-array/

class Solution {public void rotate(int[] nums, int k) {k%=nums.length;//先反转整个字符串reverse(nums,0,nums.length-1);reverse(nums,0,k-1);//先反转左边reverse(nums,k,nums.length-1);//反转右边}//反转字符串public void reverse(int[] nums,int start,int end){while(start<end){int temp=nums[start];nums[start]=nums[end];nums[end]=temp;start++;end--;}}
}

二级目录

力扣小练习(Java)相关推荐

  1. 消除游戏(力扣 390)Java

    目录 一.题目描述 二.思路讲解 三.Java代码实现 四.时空复杂度分析 五.代码优化 一.题目描述 列表 arr 由在范围 [1, n] 中的所有整数组成,并按严格递增排序.请你对 arr 应用下 ...

  2. 力扣小周推荐——最大交换

    文章目录 我的做法 更新时间复杂度更低的方法 小周让我做的一道题,俺kuakua两下,不到俩小时就做完了,虽然也不快,但也狠狠平复了轮换数组那道题的伤o(╥﹏╥)o 我的做法 思路:从第一个位置开始, ...

  3. 力扣Leetcode之Java解题406根据身高重建队列

    406. 根据身高重建队列 题目: 假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序).每个 people[i] = [hi, ki] 表示第 i 个人的身 ...

  4. 力扣---环形链表---Java

    解析: 首先判断链表是否为空或者只有一个数据. 然后将快慢指针分别指向头节点和头结点的下一个. 如果快慢指针不相等那就循环,若相等就是代表有环直接停止循环并且return true. 在while循环 ...

  5. 力扣leetcode之Java刷题121买卖股票的最佳时机

    121. 买卖股票的最佳时机 题目:   给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格.   你只能选择某一天买入这只股票,并选择在未来的某一 ...

  6. 力扣(LeetCode)官网首发!史上首本Java语言实现LeetCode题解手册

    最近小编无聊刷力扣(LeetCode)的时候看到了很多LeetCode都是用c++写的,就萌生了想给小伙伴分享一份用Java语言来实现的LeetCode题解答案: 今天就把这件事给安排了吧,分享几个用 ...

  7. 力扣455.分发饼干(java)-贪心算法思想及基本步骤

    文章目录 贪心算法核心思想 基本步骤 455.分发饼干(Java) 1.需要考虑的问题 2.方案(序号分别与问题对应) 贪心算法核心思想 贪心算法的基本思想是每一步都做出当时看起来最佳的选择,可以理解 ...

  8. 《LeetCode力扣练习》剑指 Offer 30. 包含min函数的栈 Java

    <LeetCode力扣练习>剑指 Offer 30. 包含min函数的栈 Java 一.资源 题目: 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调 ...

  9. 《LeetCode力扣练习》剑指 Offer 29. 顺时针打印矩阵 Java

    <LeetCode力扣练习>剑指 Offer 29. 顺时针打印矩阵 Java 一.资源 题目: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字. 示例 1: 输入:matr ...

最新文章

  1. [转]C#遍历局域网的几种方法及比较
  2. oracle数据库自动备份
  3. Xamarin的播放音频和视频的媒体管理插件
  4. Linux系统调用--getrusage函数详解
  5. WinXP下变量方式表达对应路径说明
  6. Android -- App生成快捷方式
  7. redis原理解析与案例分享
  8. 【Pytorch】MNIST数据集的训练和测试
  9. 日常学习随笔-数组、单链表、双链表三种形式实现队列结构的基本操作(源码注释)...
  10. 学python需要什么基础-自学Python需要怎样的基础和准备
  11. 浏览器tab切换最小化,当前页面无操作刷新页面
  12. E-prime问题(安装.net3.5)
  13. 淘宝店铺老店标识怎么显示 怎么淘宝老店标识申请
  14. 明珠三国java最新_新明珠三国下载-新明珠三国最新版下载v5.0-三国在线
  15. 珠海市世鸿置业有限公司5周年线下交流会带你学会用基金理财
  16. 基于php+mysql的 医院病房管理系统
  17. Docker容器化开发
  18. 在UniApp的H5项目中,生成二维码和扫描二维码的操作处理
  19. 计算机考研公共课考英语几,新文道教育:2022考研必须要了解的30个知识点
  20. 团购网站的发展趋势分析

热门文章

  1. 南尼U盘修复——坑die专属
  2. puppeteer 清空input原本的值
  3. 电机与matlab突然,同步电机的三相突然短路的MATLAB计算
  4. 深度:国产FPGA研究框架
  5. 关于PyTorch Geometric的安装及问题解决记录
  6. RocketMQ - 6 生产者,顺序消息
  7. 【笔记】三剑客之sed、grep sort uniq
  8. 【Unity3D】单个按键控制两个摄像机画面之间切换
  9. 定时任务 Corn表达式
  10. [BZOJ 3730] 震波