算法题整理

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值