2021-1-24开始创建~
一、链表
1.链表反转
/**
* 反转链表
*/
//1.迭代法,头插
public ListNode revList(ListNode head) {
if(head == null)return null;
ListNode pre = null,next = null;
while (head != null){
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
//2.递归
public ListNode reverseList(ListNode head){
if (head == null || head.next == null)return head;
ListNode next = head.next;
ListNode newHead = reverseList(next);
next.next = head;
head.next = null;
return newHead;
}
2.反转相邻结点
/*
交换相邻两个节点
*/
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null)return head;
//类似数组两个元素的交换
ListNode tmp = head.next;
head.next = swapPairs(tmp.next);
tmp.next = head;
return tmp;
}
3.分组反转结点
1.从头部开始分组
public ListNode reverseKGroup(ListNode head,int k){
ListNode tmp = head;
for (int i = 1; i < k&&tmp !=null; i++) {
tmp = tmp.next;
}
if (tmp == null) {
return head;
}
ListNode t2 = tmp.next;
tmp.next = null;
ListNode newHead = ReverseList(head);
head.next = reverseKGroup(t2,k);
return newHead;
}
2.从尾部开始分组,只需要先整体反转,然后从头开始分组反转,再整体反转
4. 回文链
public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) {
return true;
}
ListNode slow = head, fast = head.next;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
}
if (fast != null) {//偶数
ListNode next = slow.next;
slow.next = null;
return isEqual(head,reverseList(next));
}else {
ListNode h = head;
while(h.next != slow)h = h.next;
h.next = null;
return isEqual(head,reverseList(slow.next));
}
}
public boolean isEqual(ListNode h1,ListNode h2){
while(h1 != null && h2 !=null){
if(h1.val != h2.val)return false;
h1 = h1.next;
h2 = h2.next;
}
if(h1 != null || h2 != null)return false;
return true;
}
5.递增链表去除重复节点
1.保留一个
public ListNode removeDup(ListNode head){
if(head == null || head.next == null)return head;
ListNode next = head.next;
head.next = removeDup(next);
if(head.val == next.val)head=next;
return head;
}
2.不保留
public ListNode removeDup(ListNode head){
if(head == null || head.next == null)return head;
ListNode next = head.next;
if(head.val == next.val){
while(next != null && next.val == head.val)next = next.next;
head = removeDup(next);
}else{
head.next = removeDup(next);
}
return head;
}
6.合并k个有序链表
public ListNode mergeKLists(ListNode[] lists){
if(lists == null || lists.length == 0)return null;
return mergeK(lists,0,lists.length-1);
}
public ListNode mergeK(ListNode[] lists,int l,int r){
if(l>=r)return lists[l];
int mid = l + (r - l) / 2;
ListNode l1 = mergeK(lists,0,mid);
ListNode l2 = mergeK(lists,mid+1,r);
return merge2(l1,l2);
}
public ListNode merge2(ListNode l1,ListNode l2){
if(l1 == null)return l2;
if(l2 == null)return l1;
if(l1.val < l2.val){
l1.next = merge2(l1.next,l2);
return l1;
}else{
l2.next = merge2(l1,l2.next);
return l2;
}
}
7. 相交节点
public ListNode findCommon(ListNode l1,ListNode l2){
ListNode h1 = l1,h2 = l2;
while(h1 != h2){
h1 = h1==null?l2:h1.next;
h2 = h2==null?l1:h2.next;
}
return h1;
}
二、树
1.最大路径
private int max = 0;
public int diameterOfBinaryTree(TreeNode root) {
depth(root);
return max;
}
public int depth(TreeNode root){
if(root==null)return 0;
int left = depth(root.left);
int right = depth(root.right);
max = Math.max(max,left+right);//递归到每个节点比较一次
return Math.max(left,right)+1;
}
2.翻转树
public TreeNode invert(TreeNode root){
if(root == null)return null;
TreeNode left = root.left;
root.left = invert(root.right);
root.right = invert(left);
return root;
}
3. 合并树
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if(t1 == null && t2== null)return null;
if(t1 == null)return t2;
if(t2 == null)return t1;
TreeNode root = new TreeNode(t1.val+t2.val);
root.left = mergeTrees(t1.left,t2.left);
root.right = mergeTrees(t1.right,t2.right);
return root;
}
4. 路径和
1.根到叶节点是否存在和为sum的路径
public boolean pathSum(TreeNode root, int sum){
if(root == null)return false;
if(root.left == null && root.right == null && root.val == sum)return true;
return pathSum(root.left,sum-root.val)||pathSum(root.right,sum-root.val);
}
2.任意节点之间和为sum的路径数量
public int pathSum(TreeNode root, int sum) {
if(root == null)return 0;
return pathSumStartWithRoot(root,sum)+pathSum(root.left,sum)+pathSum(root.right,sum);
}
public int pathSumStartWithRoot(TreeNode root,int sum){
if(root == null)return 0;
int res = 0;
if(root.val == sum)res++;//不需要到达叶节点,任意即可
res += pathSumStartWithRoot(root.left,sum-root.val)+pathSumStartWithRoot(root.right,sum-root.val);
return res;
}
5. 是否是子树
public boolean isSubtree(TreeNode s,TreeNode t){
if(s == null)return false;
return isSubtreeStartWithRoot(s,t)||isSubtree(s.left,t)||isSubtree(s.right,t);
}
public boolean isSubtreeStartWithRoot(TreeNode s,TreeNode t){
if(s == null && t == null)return true;
if(s == null || t == null)return false;
if(s.val != t.val)return false;
else return isSubtreeStartWithRoot(s.left,t.left)&&isSubtreeStartWithRoot(s.right,t.right);
}
6. 是否是对称树
public boolean isSym(TreeNode root){
if(root == null)return true;
return isSym(root.left,root.right);//左右子树是否对称
}
public boolean isSym(TreeNode left,TreeNode right){
if(left == null && right == null)return true;
if(left == null || right == null)return false;
if(left.val != right.val)return false;
return isSym(left.left,right.right)&&isSym(left.right,right.left);
}
7. 非递归遍历
//非递归
void preOrderNoRecursion(TreeNode root){
Stack<TreeNode> stack = new Stack<>();
while (root != null || !stack.isEmpty()){
while (root != null){
stack.push(root);
System.out.println(root.val);
root = root.left;
}
if (!stack.isEmpty()){
root = stack.pop();
root = root.right;
}
}
}
void inOrderTravelNoRecursion(TreeNode root){
Stack<TreeNode> stack = new Stack<>();
while (root != null || !stack.isEmpty()){
while (root != null){
stack.push(root);
root = root.left;
}
if (!stack.isEmpty()){
root = stack.pop();
System.out.println(root.val);
root = root.right;
}
}
}
void postOrderTravelNoRecursion(TreeNode root){
Stack<TreeNode> stack1 = new Stack<>();
Stack<Integer> stack2 = new Stack<>();
Integer flag = new Integer(1);
while (root != null || !stack1.isEmpty()){
while (root != null){
stack1.push(root);
stack2.push(new Integer(0));
root = root.left;
}
if (!stack1.isEmpty() && stack2.peek().equals(flag)){
System.out.println(stack1.pop());
stack2.pop();
}
if (!stack1.isEmpty()){
stack2.pop();
stack2.push(new Integer(1));
root = stack1.peek();
stack1.push(root.right);
}
}
}
8. 间隔遍历
public int rob(TreeNode root) {
if (root == null)return 0;
int v1 = root.val;
if (root.left != null)v1 += rob(root.left.left)+rob(root.left.right);
if (root.right != null)v1 += rob(root.right.left)+rob(root.right.right);
int v2 = rob(root.left)+rob(root.right);
return Math.max(v1,v2);
}
9. 是否是BST
//中序遍历,判断序列是否是递增,如果不能申请额外地址空间
int last = Integer.MIN_VALUE;
public boolean isBST(TreeNode root) {
if (root == null) {
return true;
}
if (isBST(root.left)) {
if (last < root.val) {
last = root.val;
return isBST(root.right);
}
}
return false;
}
10. 公共祖先LCA
1.BST,如果当前root的值介于两节点值中间,则为公共祖先
public TreeNode lowestCommonAncestor(TreeNode root,TreeNode p,TreeNode q){
if(root.val>p.val&&root.val>q.val)return lowestCommonAncestor(root.left,p,q);
if(root.val<p.val&&root.val<q.val)return lowestCommonAncestor(root.right,p,q);
return root;
}
2.普通树
public TreeNode lowestCommonAncestor(TreeNode root,TreeNode p,TreeNode q){
if(root == null)return null;
if(root == p || root == q)return root;
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
if(left != null && right != null)return root;
if(left != null)return left;
if(right != null)return right;
return null;
}
11. 有序链表转化成AVL
如果是有序数组,则每次取中间值新建根节点,递归数组左右区间;链表同理
public TreeNode linklistToBST(ListNode head){
if(head == null)return null;
if(head.next == null)return new TreeNode(head.val);
ListNode preMid = preMid(head);
ListNode mid = preMid.next;
preMid.next = null;
TreeNode root = new TreeNode(mid.val);
root.left = linklistToBST(head);
root.right = linklistToBST(mid.next);
return root;
}
public ListNode preMid(ListNode head){
ListNode slow = head,fast = head.next,pre = head;
while(fast != null && fast.next != null){
pre = slow;
slow = slow.next;
fast = fast.next.next;
}
return pre;
}
三、矩阵
1、 顺时针打印
public ArrayList<Integer> printMatrix(int [][] matrix) {
ArrayList<Integer> result = new ArrayList<>();
int r1 = 0,r2 = matrix.length-1,c1=0,c2=matrix[0].length-1;
while (r1 <= r2 && c1 <= c2){
for (int i = c1; i <= c2; i++) result.add(matrix[r1][i]);
for (int i = r1+1;i <= r2; i++) result.add(matrix[i][c2]);
if (r1 != r2){
for (int i = c2 -1 ;i >= c1; i--)result.add(matrix[r2][i]);
}
if (c1 != c2){
for (int i = r2 - 1;i>=r1+1;i--)result.add(matrix[i][c1]);
}
r1++;r2--;c1++;c2--;
}
return result;
}
2. 最大连通子图面积
public int maxAreaOfIsland(int[][] grid) {
int res = 0;
for(int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[0].length; j++){
res = Math.max(res,dfs(grid,i,j));//判断当前坐标所在连通图是否是max
}
}
return res;
}
public int dfs(int[][] grid, int i, int j){
if(i>=0&&i<grid.length&&j>=0&&j<grid[0].length&&grid[i][j]==1){//当前位置是合理的
grid[i][j]=0;
return 1+dfs(grid,i+1,j)+dfs(grid,i-1,j)+dfs(grid,i,j+1)+dfs(grid,i,j-1);//上下左右
}
return 0;
}
3.连通子图个数
private int[][] direction = {{1,0},{-1,0},{0,1},{0,-1}};
public int numIslands(char[][] grid) {
int res = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if(grid[i][j]=='1'){
dfs(grid,i,j);
res++;
}
}
}
return res;
}
private void dfs(char[][] grid, int i, int j) {
if(i>=0&&i<grid.length&&j>=0&&j<grid[0].length&&grid[i][j]==1){//当前位置是合理的
grid[i][j]=0;
for(int k = 0; k < 4; k++){
dfs(grid,i+direction[k][0],j+direction[k][1]);//上下左右试探
}
}
}
四、 数组
1.移除元素
public int removeElement(int[] nums, int val) {
if(nums == null || nums.length == 0)return 0;
int i = 0;
for(int j = 0; j < nums.length; j++){
if(nums[j] != val){
nums[i++] = nums[j];
}
}
return i;
}
2. 移除重复元素
public int removeDupli(int[] nums){
if(nums == null || nums.length == 0)return 0;
int i = 0;
for(int j = 1; j < nums.length; j++){
if (nums[i] != nums[j])nums[++i]=nums[j];
}
return ++i;
}