算法(2)

二叉树

镜像二叉树

树轴对称

image-20220714124446238

第一个节点的左子树与第二个节点的右子树同步递归对比,第一个节点的右子树与第二个节点的左子树同步递归比较。

二叉树序列化、反序列化

image-20220714132710644

当然你也可以根据满二叉树结点位置的标号规律来序列化,还可以根据先序遍历和中序遍历的结果来序列化。不对序列化之后的字符串进行约束,所以欢迎各种奇思妙想。

思路 : 序列化树,递归前序遍历,反序列化同。序列化为字符串 1!#22! ,用!分割灭一个数值,#区分空节点。

import java.util.*;
public class Solution {
    //序列的下标
    public int index = 0;
    //处理序列化的功能函数(递归)
    private void SerializeFunction(TreeNode root, StringBuilder str) {
        //如果节点为空,表示左子节点或右子节点为空,用#表示
        if (root == null) {
            str.append('#');
            return;
        }
        //根节点
        str.append(root.val).append('!');
        //左子树
        SerializeFunction(root.left, str);
        //右子树
        SerializeFunction(root.right, str);
    }

    public String Serialize(TreeNode root) {
        //处理空树
        if (root == null)
            return "#";
        StringBuilder res = new StringBuilder();
        SerializeFunction(root, res);
        //把str转换成char
        return res.toString();
    }
    //处理反序列化的功能函数(递归)
    private TreeNode DeserializeFunction(String str) {
        //到达叶节点时,构建完毕,返回继续构建父节点
        //空节点
        if (str.charAt(index) == '#') {
            index++;
            return null;
        }
        //数字转换
        int val = 0;
        //遇到分隔符或者结尾
        while (str.charAt(index) != '!' && index != str.length()) {
            val = val * 10 + ((str.charAt(index)) - '0');
            index++;
        }
        TreeNode root = new TreeNode(val);
        //序列到底了,构建完成
        if (index == str.length())
            return root;
        else
            index++;
        //反序列化与序列化一致,都是前序
        root.left = DeserializeFunction(str);
        root.right = DeserializeFunction(str);
        return root;
    }

    public TreeNode Deserialize(String str) {
        //空序列对应空树
        if (str == "#")
            return null;
        TreeNode res = DeserializeFunction(str);
        return res;
    }
}

二叉搜索树第k节点

中序遍历返回遍历的第k个节点。

返回二叉搜索树 两个节点的最近公共祖先

思路1:返回当前节点到p和q的距离之和,能获得最小的距离就是根节点。递归,可以适用于(非有序的),题目中给定有序,那就只要判断当前节点是不是 root.val >=p&&q>=root.val 或者root.val <= p&& q>= root.val的那个节点即可。

import java.util.*;
public class Solution {

    public int lowestCommonAncestor (TreeNode root, int p, int q) {
        if (root == null) return -1;
        if (root.val >= p && root.val <= q) {
            return root.val;
        } else if (root.val <= p && root.val >= q) {
            return root.val;
        } else {
            if (root.val < p) {
                return lowestCommonAncestor(root.right, p, q);
            } else {
                return lowestCommonAncestor(root.left, p, q);
            }
        }
    }
}

思路2:题目给定二叉搜索树,有序的,那就可以分别判断两个节点p、q在当前节点的左子树还是右子树。然后再遍历的过程中记录到达p或者q遍历过的元素路径,最后比较两个路径,最后一个相同的元素即是要求节点。

import java.util.*;
public class Solution {
    //求得根节点到目标节点的路径
    public ArrayList<Integer> getPath(TreeNode root, int target) {
        ArrayList<Integer> path = new ArrayList<Integer>();
        TreeNode node = root;
        //节点值都不同,可以直接用值比较
        while(node.val != target){ 
            path.add(node.val);
            //小的在左子树
            if(target < node.val) 
                node = node.left;
            //大的在右子树
            else 
                node = node.right;
        }
        path.add(node.val);
        return path;
    }
    public int lowestCommonAncestor (TreeNode root, int p, int q) {
        //求根节点到两个节点的路径
        ArrayList<Integer> path_p = getPath(root, p); 
        ArrayList<Integer> path_q = getPath(root, q);
        int res = 0;
        //比较两个路径,找到第一个不同的点
        for(int i = 0; i < path_p.size() && i < path_q.size(); i++){ 
            int x = path_p.get(i);
            int y = path_q.get(i);
            //最后一个相同的节点就是最近公共祖先
            if(x == y) 
                res = path_p.get(i);
            else
                break;
        }
        return res;
    }
}

返回二叉树中 两个节点的最近公共祖先

二叉树,递归遍历每个节点,要求当前节点往左or右能够到达p,且往右or左能够到达q。否则往子树递归遍历。

    public int lowestCommonAncestor(TreeNode root, int o1, int o2) {
        return helper(root, o1, o2).val;
    }

    public TreeNode helper(TreeNode root, int o1, int o2) {
        if (root == null || root.val == o1 || root.val == o2)
            return root;
        TreeNode left = helper(root.left, o1, o2);
        TreeNode right = helper(root.right, o1, o2);
        //如果left为空,说明这两个节点在root结点的右子树上,我们只需要返回右子树查找的结果即可
        if (left == null)
            return right;
        //同上
        if (right == null)
            return left;
        //如果left和right都不为空,说明这两个节点一个在root的左子树上一个在root的右子树上,
        //我们只需要返回cur结点即可。
        return root;
    }

返回二叉树和为t的路径

回溯

import java.util.*;
import java.util.ArrayList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int expectNumber) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if(root==null) return res;
        ArrayList<Integer> temp = new ArrayList<> ();
        _find(res, temp, expectNumber, root);
        return res;
    }

    static void _find(ArrayList<ArrayList<Integer>> res, ArrayList<Integer> list,
                      int t, TreeNode root) {
        if (root.left == null && root.right == null) {
            if (root.val == t) {
                list.add(root.val);
                ArrayList<Integer> ls = new ArrayList<>(list);
                list.remove(list.size() - 1);
                res.add(ls);
                return ;
            }
            else return ;
        }
        if (root.left == null) {
            list.add(root.val);
            _find(res, list, t - root.val, root.right);
            list.remove(list.size() - 1);
            return ;
        }
        if (root.right == null) {
            list.add(root.val);
            _find(res, list, t - root.val, root.left);
            list.remove(list.size() - 1);
            return ;
        }

        list.add(root.val);
        _find(res, list, t - root.val, root.left);
        _find(res, list, t - root.val, root.right);
        list.remove(list.size() - 1);
    }
}

平衡二叉树判断

递归的判断左右子树是否平衡,平衡继续判断当前节点的左子树和右子树的高度差是否满足小于2要求。满足返回true,否则返回false。

public class Solution {
    public boolean IsBalanced_Solution(TreeNode root) {
        if (root == null) return true;
        //判断左子树和右子树是否符合规则,且深度不能超过2
        //先递归判断左子树 右子树 是否符合规则,否则判断当前节点的的左子树和右子树的高度差是否小于2
        return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right) && Math.abs(deep(root.left) - deep(root.right)) < 2;
    }
    
    //判断二叉树深度
    public int deep(TreeNode root) {
        if (root == null) return 0;
        return Math.max(deep(root.left), deep(root.right)) + 1;
    }
}

链表

复杂链表深拷贝

image-20220714173043585

import java.util.*;
/*
public class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}
*/
public class Solution {
    public RandomListNode Clone(RandomListNode pHead) {
        if (pHead == null) return null;
        RandomListNode node =  pHead;
        RandomListNode head = null;
        RandomListNode temp = null;
        HashMap<RandomListNode, RandomListNode> map = new HashMap<>();
        while (node != null) {
            if (head == null) {
                RandomListNode rn = new RandomListNode(node.label);
                head = rn;
                temp = rn;
                map.put(node, temp);
            } else {
                temp.next = new RandomListNode(node.label);
                map.put(node, temp.next);
                temp = temp.next;
            }
            node = node.next;
        }

        while (pHead != null) {
            if (pHead.random != null)
                map.get(pHead).random = map.get(pHead.random);
            pHead = pHead .next;
        }
        return head;
    }

}

递归回溯

n皇后

找到对角线数组与行、列号的关系。

import java.util.*;


public class Solution {
    /**
     *
     * @param n int整型 the n
     * @return int整型
     */
    static int count = 0;
    public int Nqueen (int n) {
        // write code here
        //记录行列 斜对角线是否摆放过
        boolean r [] = new boolean [n];
        boolean l [] = new boolean [n];

        //正对角线 n-j-1+i
        boolean tx[] = new boolean [2 * n - 1];
        //斜对角线 i+j
        boolean rx[] = new boolean [2 * n - 1];

        //放第一个
//         for (int i = 0; i < n; i++) 
            dfs(r, l, rx, tx, 0);
//         }
//         System.out.println(count);
        return count;
    }

    static void dfs(boolean r[], boolean l[], boolean rx[], boolean tx[],
                    int index) {
        if (index == r.length) {
            count++;
            return ;
        }

        int n = r.length;
        //试探第j列
        for (int j = 0; j < n; j++) {
            if (!r[index] && !l[j] && !tx[n - j - 1 + index] && !rx[index + j]) {
                r[index] = true;
                l[j] = true;
                tx[n - j - 1 + index] = true;
                rx[index + j] = true;
                
                dfs(r, l, rx, tx, index + 1);
                
                r[index] = false;
                l[j] = false;
                tx[n - j - 1 + index] = false;
                rx[index + j] = false;
            }
        }
    }

}

矩阵最长路径问题

给定矩阵求最长递增序列长度。起点终点不限,智能上下左右。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PYvX44xs-1690389890287)(https://s2.loli.net/2022/07/15/vkDchA2qdfSGeIK.png)]

递归

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 递增路径的最大长度
     * @param matrix int整型二维数组 描述矩阵的每个数
     * @return int整型
     */
    public int solve (int[][] matrix) {
        // write code here
        //深度优先搜索
        int dis = 0;
        boolean maze[][] = new boolean [matrix.length][matrix[0].length];
        int m = 0;
        int r = matrix.length;
        int l = matrix[0].length;

        for (int i = 0; i < r; i++) {
            for (int j = 0; j < l; j++) {
                m = Math.max(_dfs(i, j, maze, matrix) + 1, m);
            }
        }
        return m;
    }

    static int _dfs(int x, int y, boolean [][]maze, int matrix[][]) {
        int r = maze.length;
        int l = maze[0].length;
        int max = 0;
        maze[x][y] = true;
        int v = matrix[x][y];
        //右
        if (y < l - 1 && !maze[x][y + 1] && matrix[x][y + 1] > v) {
            max = Math.max(_dfs(x, y + 1, maze,matrix) + 1, max);
        }
        //下
        if (x < r - 1 && !maze[x + 1][y] && matrix[x + 1][y] > v) {
            max = Math.max(_dfs(x + 1, y, maze,matrix) + 1, max);
        }

        if (x > 0 && !maze[x - 1][y] && matrix[x - 1][y] > v) {
            max = Math.max(_dfs(x - 1, y, maze,matrix) + 1, max);
        }
        if (y > 0 && !maze[x][y - 1] && matrix[x][y - 1] > v) {
            max = Math.max(_dfs(x, y - 1, maze,matrix) + 1, max);
        }
        maze[x][y] = false;
        return max;
    }
}

dp优化,dp[x][y]表示从x,y开始所能拓展到的最长递增序列长度。当后面再次遍历到x,y节点可以直接返回。同时maze不需要,因为每一步都是也只能往高处走,不会往回走的情况。

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 递增路径的最大长度
     * @param matrix int整型二维数组 描述矩阵的每个数
     * @return int整型
     */
    public int solve (int[][] matrix) {
        // write code here
        //深度优先搜索
        //矩阵不为空
        if (matrix.length == 0 || matrix[0].length == 0)
            return 0;

//         boolean maze[][] = new boolean [matrix.length][matrix[0].length];
        int m = 0;
        int r = matrix.length;
        int l = matrix[0].length;
        int dp [][] = new int[r][l];

        for (int i = 0; i < r; i++) {
            for (int j = 0; j < l; j++) {
                m = Math.max(_dfs(i, j, matrix, dp), m);
            }
        }
        return m;
    }

    static int _dfs(int x, int y,  int matrix[][], int dp[][]) {
        //优化 减少递归
        if (dp[x][y] != 0) return dp[x][y];

        int r = matrix.length;
        int l = matrix[0].length;

        int max = 1;
        

        int v = matrix[x][y];
        //右
        if (y < l - 1 && matrix[x][y + 1] > v) {
            max = Math.max(_dfs(x, y + 1, matrix, dp) + 1, max);
        }
        //下
        if (x < r - 1  && matrix[x + 1][y] > v) {
            max = Math.max(_dfs(x + 1, y, matrix, dp) + 1, max);
        }

        if (x > 0  && matrix[x - 1][y] > v) {
            max = Math.max(_dfs(x - 1, y, matrix, dp) + 1, max);
        }
        if (y > 0  && matrix[x][y - 1] > v) {
            max = Math.max(_dfs(x, y - 1, matrix, dp) + 1, max);
        }
        //表示从dp[x][y] 拓展的最长递增子序列长度
        dp[x][y] = max;

        return max;
    }
}

贪心

活动安排

给定各个活动的开始结束时间,要求最大活动数量。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;


public class Main {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        //创建一个集合存储数据
        List<Node> xD = new ArrayList<Node>();

        Node node;

        for (int i = 0; i < n; i++) {
            //数据类型的起始值
            int a = scanner.nextInt();
            int b = scanner.nextInt();
            node = new Node(a, b);
            //将活动对应的起始和结束时间加入集合
            xD.add(node);
        }

        //对活动时间进行排序,按照末尾时间从小到大的标准
        Collections.sort(xD, (o1, o2)-> {
            return o1.end - o2.end;
        });

        int begin = 0, count = 0;
        for (int i = 0; i < n; i++) {
            //当当前的起始值大于上一个活动的结束值时,符合要求
            if (xD.get(i).start >= begin) {
                //更新begin的值
                begin = xD.get(i).end;
                count++;
            }
        }
        System.out.println(count);
    }

}


//节点类
class Node {
    //该数据类型包含一个起始值,一个结束值,一个标记,
    int start;
    int end;
    public Node(int start, int end) {
        // TODO Auto-generated constructor stub
        this.start = start;
        this.end = end;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/46736.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

余切拉普拉斯算子推导 cotangent Laplace-Beltrami operator

欢迎关注更多精彩 关注我&#xff0c;学习常用算法与数据结构&#xff0c;一题多解&#xff0c;降维打击。 参考自polygon mesh proccessing这本书 基本思路及原理 余切拉普拉斯算子是一种考虑了网格底层几何联系的一种算子&#xff0c;在网格平滑&#xff0c;参数化等算法中…

Llama 2: Open Foundation and Fine-Tuned Chat Models

文章目录 TL;DRIntroduction背景本文方案 实现方式预训练预训练数据训练细节训练硬件支持预训练碳足迹 微调SFTSFT 训练细节 RLHF人类偏好数据收集奖励模型迭代式微调&#xff08;RLHF&#xff09;拒绝采样&#xff08;Rejection Sampling&#xff09;PPO多轮一致性的系统消息&…

2023 年第二届钉钉杯大学生大数据挑战赛 初赛 B:美国纽约公共自行车使用量预测分析 问题二Python代码分析

2023 年第二届钉钉杯大学生大数据挑战赛 初赛 B&#xff1a;美国纽约公共自行车使用量预测分析 问题二 相关链接 【2023 年第二届钉钉杯大学生大数据挑战赛】 初赛 B&#xff1a;美国纽约公共自行车使用量预测分析 问题一Python代码分析 【2023 年第二届钉钉杯大学生大数据挑…

Tensorflow学习

一、处理数据的结构 案例代码如下: import tensorflow.compat.v1 as tf tf.disable_v2_behavior() import numpy as np# create data x_data np.random.rand(100).astype(np.float32) y_data x_data*0.1 0.3# 创建结构(一维结构) Weights tf.Variable(tf.random.uniform(…

Megatron-LM、NVIDIA NeMo、model_optim_rng.pt 文件是什么?

本文涉及以下几个概念&#xff0c;分别是&#xff1a; Megatron和Megatron-LM-v1.1.5-3D_parallelism NVIDIA NeMo Megatron和Megatron-LM-v1.1.5-3D_parallelism是什么&#xff1f; Megatron是由NVIDIA开发的一种用于训练大规模语言模型的开源框架。它旨在提供高效的分布式…

安科瑞能源物联网以能源供应、能源管理、设备管理、能耗分析的能源流向为主线-安科瑞黄安南

摘要&#xff1a;随着科学技术的发展&#xff0c;我国的物联网技术有了很大进展。为了提升电力抄表服务的稳定性&#xff0c;保障电力抄表数据的可靠性&#xff0c;本文提出并实现了基于物联网的智能电力抄表服务平台&#xff0c;结合云计算、大数据等技术&#xff0c;提供电力…

雷达信号处理自学总结(持续更新)

傅里叶变换的频率分辨率 频率分辨率 采样频率 信号长度 频率分辨率 \frac{采样频率 }{信号长度} 频率分辨率信号长度采样频率​ 可用numpy模块的fft.fftfreq函数求出傅里叶变换的频率分辨率。 https://numpy.org/doc/stable/reference/generated/numpy.fft.fftfreq.html

opencv 图像距离变换 distanceTransform

图像距离变换&#xff1a;计算图像中每一个非零点距离离自己最近的零点的距离&#xff0c;然后通过二值化0与非0绘制图像。 #include "iostream" #include "opencv2/opencv.hpp" using namespace std; using namespace cv;int main() {Mat img, dst, dst…

关于position:fixed定位的位置不对的问题(即没有按照浏览器的窗口进行定位)

问题&#xff1a; 今天在开发过程中发现元素使用 position: fixed 时位置有问题&#xff0c;位置跟我写的位置对不上&#xff0c;后面在 MDN 上面找到了答案&#xff0c;下面是关于 position: fixed 的描述&#xff1a; fixed&#xff1a; 元素会被移出正常文档流&#xff0c;并…

通过Vue-cli解决前端跨域问题

1、找到vue.config.js 在vue.config.js当中增加如下配置 devServer: {port: 3001,proxy: {/agent: {target: http://10.8.50.250:6666,ws: false, //true,开启ws, 如果是http代理此处可以不用设置changeOrigin: true, // 如果接口跨域&#xff0c;需要进行这个参…

Rust之包、单元包及模块

包&#xff1a;一个用于构建、测试并分享单元包的Cargo功能&#xff1b;单元包&#xff1a;一个用于生成库或可执行文件的树形模块结构&#xff1b;模块及use关键字&#xff1a;被用于控制文件结构、作用域及路径的私有性&#xff1b;路径&#xff1a;一种用于命名条目的方法&a…

【电商小知识】7个步骤让你快速了解跨境电商!

近几年来&#xff0c;随着互联网的发展&#xff0c;国内外的商业贸易越来越流畅&#xff0c;直播电商的火爆也带动着一大批相关的产业链发展&#xff0c;其中跨境电商就是尤为突出的一个。尽管在国内做跨境电商的企业数量非常之多&#xff0c;但仍有许多新人争相入局&#xff0…

安防监控视频汇聚平台EasyCVR修改录像计划等待时间较长是什么原因?

安防监控视频EasyCVR视频融合汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发等。音视频流媒体视频平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、云存储、回放与检…

Ceph部署方法介绍

Ceph部署方法介绍 Installing Ceph — Ceph Documentation Ceph环境规划 admin是一个部署节点

计算机视觉:图像质量评价指标之 PSNR 和 SSIM

1. PSNR (Peak Signal-to-Noise Ratio) 峰值信噪比 由上可见&#xff0c;PSNR相对MSE多了一个峰值&#xff0c;MSE是绝对误差&#xff0c;再加上峰值是一个相对误差指标 一般地&#xff0c;针对 uint8 数据&#xff0c;最大像素值为 255,&#xff1b;针对浮点型数据&#xff…

低代码开发重要工具:jvs-flow(流程引擎)审批功能配置说明

流程引擎场景介绍 流程引擎基于一组节点与执行界面&#xff0c;通过人机交互的形式自动地执行和协调各个任务和活动。它可以实现任务的分配、协作、路由和跟踪。通过流程引擎&#xff0c;组织能够实现业务流程的优化、标准化和自动化&#xff0c;提高工作效率和质量。 在企业…

Python(Web时代)——初识flask

flask简介 介绍 Flask是一个用Python编写的Web 微框架&#xff0c;让我们可以使用Python语言快速实现一个网站或Web服务。它是BSD授权的&#xff0c;一个有少量限制的免费软件许可。它使用了 Werkzeug 工具箱和 Jinja2 模板引擎。 Flask 的设计理念是简单、灵活、易于扩展&a…

Java后端程序员不得不知道的 API 接口常识

说实话&#xff0c;我非常希望自己能早点看到本篇文章&#xff0c;大学那个时候懵懵懂懂&#xff0c;跟着网上的免费教程做了一个购物商城就屁颠屁颠往简历上写。 至今我仍清晰地记得&#xff0c;那个电商教程是怎么定义接口的&#xff1a; 管它是增加、修改、删除、带参查询&…

【Hammerstein模型的级联】快速估计构成一连串哈默斯坦模型的结构元素研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码实现 &#x1f4a5;1 概述 在许多振动应用中&#xff0c;所研究的系统略微非线性。Hammerstein模型的级联可以方便地描述这样的系统。Hammerstein提供了一种基于指数正弦…

关于在虚拟机CentOS7的Docker下安装Oracle

这不三阶段了&#xff0c;要上Oracle了&#xff0c;感觉这个班卷的程度到位。二阶段我就上了ElementUI和MyBatis&#xff0c;项目也是用这些技术写的&#xff0c;整体钻研程度还行。于是布置了两个任务&#xff1a;在windows下安一下Oracle&#xff0c;在windows下安装Oracle那…