数据结构-树及相关算法

news2024/10/7 4:27:05

二叉树

递归算法的关键要明确函数的定义,相信这个定义,而不要跳进递归细节。

写二叉树的算法题,都是基于递归框架的,我们先要搞清楚 root 节点它自己要做什么,然后根据题目要求选择使用前序,中序,后续的递归框架。

二叉树题目的难点在于如何通过题目的要求思考出每一个节点需要做什么,这个只能通过多刷题进行练习了。

二叉树遍历框架:

/* 二叉树遍历框架 */
void traverse(TreeNode root) {
    // 前序遍历
    traverse(root.left)
    // 中序遍历
    traverse(root.right)
    // 后序遍历
}

1,2,3,4,5,6,7

前序遍历:先输出父节点,再遍历左子树和右子树。1, 2, 4, 5, 3, 6, 7

中序遍历:先遍历左子树,在输出父节点,再遍历右子树。4, 2, 5, 1, 6, 3, 7

后序遍历:先遍历左子树,再遍历右子树,最后输出父节点。4, 5, 2, 6, 7, 3, 1

镜像翻转二叉树

剑指 Offer 27. 二叉树的镜像

这个函数的定义就是给我一个节点,我把他的左右子节点翻转
只去想一个节点翻转需要怎么做,这是一个二叉树的前序遍历

public TreeNode invertTree(TreeNode root) {
        if (root == null) {
		return root;
	}
	//翻转
	TreeNode tempNode = root.left;
	root.left = root.right;
	root.right = tempNode;
	//子节点也去翻转
	invertTree(root.left);
	invertTree(root.right);
	return root;
}

116. 填充每个节点的下一个右侧节点指针

我辅助函数定义就是将你传给我的两个节点,进行连接。
采用前序遍历,然后需要把这两个节点各自的左右节点连接&&这一个节点的左和一个节点的有连接。

// 主函数
Node connect(Node root) {
    if (root == null) return null;
    connectTwoNode(root.left, root.right);
    return root;
}

// 辅助函数
void connectTwoNode(Node node1, Node node2) {
    if (node1 == null || node2 == null) {
        return;
    }
    /**** 前序遍历位置 ****/
    // 将传入的两个节点连接
    node1.next = node2;

    // 连接相同父节点的两个子节点
    connectTwoNode(node1.left, node1.right);
    connectTwoNode(node2.left, node2.right);
    // 连接跨越父节点的两个子节点
    connectTwoNode(node1.right, node2.left);
}

114. 二叉树展开为链表

这个函数的定义是:以传给我的头节点的二叉树拉平成一个链表。

进行后序遍历

具体:把他的左右先进行拉平,然后把左树当做右树,左边为null,最后把原来的右树放到现在右树的下面。

// 定义:将以 root 为根的树拉平为链表
void flatten(TreeNode root) {
    // base case
    if (root == null) return;

    flatten(root.left);
    flatten(root.right);

    /**** 后序遍历位置 ****/
    // 1、左右子树已经被拉平成一条链表
    TreeNode left = root.left;
    TreeNode right = root.right;

    // 2、将左子树作为右子树
    root.left = null;
    root.right = left;

    // 3、将原先的右子树接到当前右子树的末端
    TreeNode p = root;
    while (p.right != null) {
        p = p.right;
    }
    p.right = right;
}

654. 最大二叉树

test函数的定义:返回给定的数组中的最大值new出的节点。

采用前序遍历,

public TreeNode constructMaximumBinaryTree(int[] nums) {
		return test(nums, 0, nums.length - 1);
    }

	public TreeNode test(int[] nums, int start, int end){
		if (start > end) {
			return null;
		}
		int index = start;
		int max = nums[start];
		for (int i = start + 1; i <= end; i++) {
			if (max < nums[i]) {
				max = nums[i];
				index = i;
			}
		}
		TreeNode node = new TreeNode(max);

		node.left = test(nums, start, index - 1);
		node.right = test(nums, index +1, end);
		return node;
	}

105. 从前序与中序遍历序列构造二叉树

辅助函数的定义:通过给定的前序,中序数组找到根节点。

流程:根据前序遍历可以知道,根节点就是前序遍历的首位,根节点的下一位就是前序遍历数组的下一位,在通过中序遍历数组就可以确定是左右哪个节点。然后分开去求左右子树。

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
		return test(preorder, 0, preorder.length -1 , inorder, 0 , inorder.length-1);
    }

	public TreeNode test(int[] preorder,int prestart, int preend, int[] inorder, int instart, int inend) {
		if (prestart > preend) {
			return null;
		}
		int index = 0;
		for (int i = instart; i <= inend; i++) {
			if (preorder[prestart] == inorder[i]) {
				index = i;
				break;
			}
		}
		TreeNode node = new TreeNode(preorder[prestart]);
		int size = index - instart;
		node.left = test(preorder, prestart + 1, size + prestart, inorder, instart, index -1);
		node.right = test(preorder, size +prestart + 1, preend, inorder, index + 1, inend);
		return node;
	}
}

106. 从中序与后序遍历序列构造二叉树

和上一题原理相同。

根节点的遍历从后序遍历的末尾开始。

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
		return build(inorder, 0, inorder.length-1, postorder, postorder.length - 1, 0);
    }

	public TreeNode build(int[] inorder,int instart, int inend, int[] postorder, int postend, int poststart) {
		if (postend < poststart) {
			return null;
		}
		int index = 0;
		for (int i = 0; i < inorder.length; i++) {
			if (postorder[postend] == inorder[i]) {
				index = i;
				break;
			}
		}
		int size = index - instart;
		TreeNode node = new TreeNode(postorder[postend]);
		node.left = build(inorder, instart, index - 1, postorder, poststart + size-1, poststart);
		node.right = build(inorder, index + 1, inend, postorder, postend - 1, poststart +size);

		return node;
	}
}

652. 寻找重复的子树

思考:我想要查看有没有重复的子树,首先我要获取到所有的子树,在获取的途中,进行查看是否已经获取过了,获取过了我就放到集合里。

如何获取一个子树呢?

获取自己下面的所有节点,在加上自己不就是一个子树了(所以用后序遍历)。然后放到集合里。

怎样把一个子树串联起来呢,->序列化,用字符串拼接。

class Solution {
    public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
        if (root == null) {
			return null;
		}
        findMap(root);
  
        return list;
    }
	Map<String, Integer> map = new HashMap<>();
    List<TreeNode> list = new ArrayList<>();

	public String findMap(TreeNode root){
		if (root == null) {
			return "#";
		}
		String s1 = findMap(root.left);
		String s2 = findMap(root.right);
		String s = root.val+"," + s1+"," + s2;
		if (map.containsKey(s)) {
			if (map.get(s) == 1) {
				list.add(root);
			}
			map.put(s, map.get(s) + 1);
		}else {
			map.put(s, 1);
		}
		return s;
	}
}

难理解236. 二叉树的最近公共祖先

遇到任何递归型的问题,无非就是灵魂三问

1、这个函数是干嘛的

2、这个函数参数中的变量是什么的是什么

3、得到函数的递归结果,你应该干什么

TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    // base case
    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);
    // 情况 1
    if (left != null && right != null) {
        return root;
    }
    // 情况 2
    if (left == null && right == null) {
        return null;
    }
    // 情况 3
    return left == null ? right : left;
}

有点难理解。。。

计算二叉树的总节点数(三种 )

/**
	 * 普通二叉树计算节点总数
	 * @param node
	 * @return
	 */
	public static int getCount1(TreeNode node) {
		if (node == null) {
			return 0;
		}
		return 1 + getCount1(node.left) + getCount1(node.right);
	}
	/**
	 * 满二叉树计算节点总数, 满二叉树就是每一层的节点数都是满的
	 * @param node
	 * @return
	 */
	public static int getCount2(TreeNode node) {
		int high = 0;
		while (node != null) {
			high ++;
			node = node.left;
		}
		return (int)Math.pow(2, high) - 1;
	}
	/**
	 * 计算完全二叉树的节点总数
	 * @param node
	 * @return
	 */
	public static int getCount3(TreeNode node) {
		TreeNode lNode = node;
		TreeNode rNode = node;
		int l = 0;
		while (lNode != null) {
			l ++;
			lNode = lNode.left;
		}
		int r = 0;
		while (rNode != null) {
			l ++;
			rNode = rNode.left;
		}
		if (l == r) {
			return (int)Math.pow(2, l) - 1;
		}
		return 1+getCount3(node.left) + getCount3(node.right);
	}

二叉搜索树

从做算法题的角度来看 BST,除了它的定义,还有一个重要的性质:BST 的中序遍历结果是有序的(升序)。如果先进行右边的递归,就会是降序。(例题:寻找第k小的值,转化为累加树)

二叉搜索树衍生框架:

void BST(TreeNode root, int target) {
    if (root.val == target)
        // 找到目标,做点什么
    if (root.val < target) 
        BST(root.right, target);
    if (root.val > target)
        BST(root.left, target);
}

98. 验证二叉搜索树

因为只有一个根节点只能判断左右孩子的是否符合,所以需要一个辅助函数。

辅助函数定义:验证当前节点是否是大于min小于max。

public boolean isValidBST(TreeNode root) {
		return judge(root, null, null);
    }
	/**
	 * 要求:max.min > root.val > min.val
	 * @param root
	 * @param min
	 * @param max
	 * @return
	 */
	public boolean judge(TreeNode root, TreeNode min, TreeNode max) {
		if (root == null) {
			return true;
		}
		if (min != null && min.val >= root.val) {
			return false;
		}
		if (max != null && max.val <= root.val) {
			return false;
		}
		return judge(root.left, min, root) && judge(root.right, root, max);
	}

450. 删除二叉搜索树中的节点

删除分为三种情况,1,要删除的节点是末尾节点。2,只有一个非空节点,3,有两个孩子。分别讨论。

第三种情况的时候:先找到要删除节点的右子树的最小值,记录下值,然后删掉,然后把值给要删除的节点。

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
		if (root == null) {
			return null;
		}
        if (root.val == key) {
			//删除 分为两种删除,在末尾直接删除,在中间(左右都存在和存在一个孩子)就要判断了
        	if (root.left == null && root.right == null) {
				return null;
			}
        	if (root.left == null || root.right == null) {
				if (root.left == null) {
					return root.right;
				}else {
					return root.left;
				}
			}
        	//左右孩子都存在
        	//首先找到右子树中最小的节点
        	TreeNode minNode = getMin(root.right);
        	//删除最小的节点
        	root.right = deleteNode1(root.right, minNode.val);
        	root.val = minNode.val;
		}else if(root.val > key) {
			root.left = deleteNode(root.left, key);
		}else {
			root.right = deleteNode(root.right, key);
		}
        return root;
    }

	public TreeNode getMin(TreeNode node) {
		if (node.left == null) {
			return node;
		}
		return getMin(node.left);
	}

	public TreeNode deleteNode1(TreeNode node, int val) {
		if (node == null) {
			return null;
		}
        if (node.val == val) {
			if (node.right != null) {
				return node.right;
			}
			return null;
		}else if(node.val > val) {
			node.left = deleteNode1(node.left, val);
		}
        return node;
	}
}

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

说明:使用辅助指针记录上一个节点和头结点。

class Solution {
    Node pre,head;
    public Node treeToDoublyList(Node root) {
        if(root == null){
            return null;
        }
        dfs(root);
        head.left = pre;
        pre.right = head;
        return head;
    }

    private void dfs(Node root) {
        if(root == null){
            return;
        }
        dfs(root.left);
        if (pre == null){
            head = root;
        }else{
            pre.right = root;
        }
        root.left = pre;
        pre = root;
        dfs(root.right);
    }
}

二叉树的序列化

前序遍历实现

先进行序列化,然后在反序列化

public class Codec {

    // Encodes a tree to a single string.
    public  String serialize(TreeNode root) {
        if (root == null) {
			return "#";
		}
        String str = root.val+",";
        String left = serialize(root.left);
        String right =  serialize(root.right);
        str = str + left + "," + right;
        return str;
    }

    // Decodes your encoded data to tree.
    LinkedList<Integer> linkedList = new LinkedList<>();
    public  TreeNode deserialize(String data) {
    	String[] arr = data.split(",");
    	for (String string : arr) {
    		if (string.equals("#")) {
				linkedList.add(null);
			}else {
				linkedList.add(Integer.parseInt(string));
			}
		} 
        return getTreeNode();
    }
    public  TreeNode getTreeNode() {
    	if (linkedList.isEmpty()) {
			return null;
		}
    	Integer numInteger = linkedList.removeFirst();
    	if (numInteger == null) {
			return null;
		}
    	TreeNode rootNode = new TreeNode(numInteger);
    	rootNode.left = getTreeNode();
    	rootNode.right = getTreeNode();
    	return rootNode;
    }
}

后序遍历实现道理相同,就不写代码了。

中序遍历可以序列化,但是序列化后的字符串不能反序列化。

层级遍历实现

层序遍历的代码框架

void traverse(TreeNode root) {
    if (root == null) return;
    // 初始化队列,将 root 加入队列
    Queue<TreeNode> q = new LinkedList<>();
    q.offer(root);

    while (!q.isEmpty()) {
        TreeNode cur = q.poll();

        /* 层级遍历代码位置 */
        System.out.println(root.val);
        /*****************/

        if (cur.left != null) {
            q.offer(cur.left);
        }

        if (cur.right != null) {
            q.offer(cur.right);
        }
    }
}

用层序遍历实现序列化:

public static String serialize(TreeNode root) {
        if (root == null) {
			return "#";
		}
        String str = "";
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
			TreeNode curNode = queue.poll();
			if (curNode == null) {
				str += "#,";
				continue;
			}
			str += curNode.val + ",";
			queue.offer(curNode.left);
			queue.offer(curNode.right);

		}
        return str;
    }

反序列化实现需要使用两个队列

static LinkedList<TreeNode> linkedList = new LinkedList<>();
    public static TreeNode deserialize(String data) {
    	String[] arr = data.split(",");
    	for (String string : arr) {
    		if (string.equals("#")) {
				linkedList.add(null);
			}else {
				linkedList.add(new TreeNode(Integer.parseInt(string)));
			}
		} 
        return getTreeNode();
    }
    public static TreeNode getTreeNode() {
    	Queue<TreeNode> queue1 = new LinkedList<>();
    	TreeNode node = linkedList.poll();
    	queue1.offer(node);
    	while (!queue1.isEmpty()) {
			TreeNode root = queue1.poll();
			root.left = linkedList.poll();
			root.right = linkedList.poll();
			if (root.left != null) {
				queue1.offer(root.left);
			}
			if (root.right != null) {
				queue1.offer(root.right);
			}
		}
    	return node;
  
    }

N叉树

class NestedInteger {
    Integer val;
    List<NestedInteger> list;
}

/* 基本的 N 叉树节点 */
class TreeNode {
    int val;
    TreeNode[] children;
}

n叉树遍历框架

void traverse(TreeNode root) {
    for (TreeNode child : root.children)
        traverse(child);

341. 扁平化嵌套列表迭代器

解析地址

赫夫曼树

概念

给定n个权值作为n个叶子结点,构造一颗二叉树,若该树的带权路径长度(wpl达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树。

赫夫曼树是带权路径长度最短的树,权值较大的节点离根较近。

路径和路径长度:在一棵数中,从一个节点往下可以达到的孩子或孙子节点之间的通路,称为路径。通路中分支的数目称为路径长度,若规定根节点的层数为1,则从根节点到第L层节点的路径长度为L-1;

节点的权和带权路径长度:若将树中节点赋给一个有着某种含义的数值,则这个数值称为该节点的权节点的带权路径长度为:从根节点到改节点之间的路径长度与该节点的权的乘积。

树的带权路径长度:树的带权路径长度是所有叶子结点的带权路径长度之和,记为wpl,权值越大的节点离根节点越近的二叉树才是最优二叉树。wpl最小的就是赫夫曼树。

节点的带权路径之和就是该树的带权路径长度wpl。

构键赫夫曼树代码:

image.png

 /**
     * 构建赫夫曼树
     * @param arr  要构建的赫夫曼树的叶子结点的权值数组
     * @return 返回赫夫曼树的头结点
     */
    public static TreeNode createHuffmanTree(int[] arr){
        List<TreeNode> nodes = new ArrayList<>();
        for (int i : arr) {
            nodes.add(new TreeNode(i));
        }

        while (nodes.size() > 1){
            //1,排序从小到大
            nodes.sort(Comparator.comparingInt(x -> x.val));
            //取出根节点最小的两颗树
            TreeNode left = nodes.get(0);
            TreeNode right = nodes.get(1);
            //构建一个新的二叉树
            TreeNode parent = new TreeNode(left.val + right.val);
            parent.left = left;
            parent.right = right;
            //从list中删除处理过的二叉树
            nodes.remove(left);
            nodes.remove(right);
            //将parent放入list中
            nodes.add(parent);
        }
        System.out.println(nodes);
        return nodes.get(0);
    }
//输入:{32,2,42}
//结果:
/**
          76
       34    42
     2   32
*/


赫夫曼编码

概念

赫夫曼编码也称 哈夫曼编码,又称霍夫曼编码,是一种编码方式,属于一种程序算法。

赫夫曼编码是赫夫曼树在电讯通信中的经典应用之一。

赫夫曼编码广泛的用于数据文件压缩,压缩率在20%-90%之间

赫夫曼码是可变字长编码(VLC)的一种。

彩蛋

加入我的知识星球,加入自学编程者的聚集地。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

colmap使用教程

COLMAP 是具有图形和命令行界面的通用运动结构 (SfM) 和多视图立体 (MVS) 管道。 它为有序和无序图像集的重建提供了广泛的功能。 常见的基于nerf算法均需要colmap来计算位姿 安装colmap&#xff1a; conda install colmap 需要使用python9 step1&#xff1a;准备多视角图…

第十三节 I/O流与文件操作

文件读写 输入输出流 文本文件 一个字节一个字节写 8位十进制最大255 int read() throws IOException 字节 java.io.OutputStream 将十进制数按字节 用文件的类 表达文件 1.txt 相对路径 &#xff1a;工程是同级的 绝对路径C盘下 D 万物皆对象 都能封装成对象…

xss-flash钓鱼配合msf捆绑上线

这里写目录标题 一&#xff0c;后门文件生成与制作二&#xff0c;flash安装钓鱼网站搭建三&#xff0c;监听四&#xff0c;钓鱼 一&#xff0c;后门文件生成与制作 打开kali&#xff0c;查看ip add 查看 ip 地址为 192.168.1.8 输入 msfconsole 1.生成后门 msfvenom -p window…

LeetCode 1026. Maximum Difference Between Node and Ancestor【DFS,BFS,树】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

Direct3D 12——模板——平面镜效果

1.将实物照常渲染到后台缓冲区内&#xff08;不包括镜子&#xff09;。注意&#xff0c;此步骤不修改模 板缓冲区。 2.清理模板缓冲区&#xff0c;将其整体置零。 将实物都绘制到后台缓冲区中&#xff0c;并将模板缓冲区清理为0 &#xff08;用浅灰色来表示&#xff09;。 绘…

socked编程

socket是什么&#xff1f;套接字是什么&#xff1f; 什么是 socket&#xff1f; socket 的原意是“插座”&#xff0c;在计算机通信领域&#xff0c;socket 被翻译为“套接字”&#xff0c;它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定&#xff0c;一台…

Motion Planning学习笔记一:配置空间、图、图搜索、图遍历

学习高飞博士的路径规划课程所总结的学习笔记。 目录 1、配置空间&#xff08;Configuration Space, C-space&#xff09; 2、图&#xff08;Graphs&#xff09; 3、图搜索&#xff08;Graph Search Basis&#xff09; 3.1、总体框架 3.2、两种基本的图遍历算法 3.3、启…

漫谈大数据 - HiveSQL总结(二)查询操作

导语&#xff1a;HiveSQL各关键字详解&#xff0c;hive函数大全&#xff0c;类似于个人记录工具书&#xff0c;后续遇到其他的也会继续加进来。 有关hive库表操作请见上篇&#xff1a;漫谈大数据 - HiveSQL总结&#xff08;一&#xff09;库表操作_昊昊该干饭了的博客-CSDN博客…

一条SQL如何被MySQL架构中的各个组件操作执行的?

文章目录 1. 单表查询SQL在MySQL架构中的各个组件的执行过程2. SELECT的各个关键字在哪里执行&#xff1f;3. 表关联查询SQL在MySQL架构中的各个组件的执行过程4. LEFT JOIN将过滤条件放在子查询中再关联和放在WHERE子句上有什么区别&#xff1f;5. 聚集索引和全表扫描有什么区…

推动开发者平台本土化,高通加速中国XR内容生态发展

随着VR和AR技术快速发展&#xff0c;产品不断成熟&#xff0c;体验也变得越来越优秀。据悉&#xff0c;Meta Quest系列VR头显出货量超2000万台&#xff0c;基本证明了VR开始在消费类电子产品中占据一席之地。与此同时&#xff0c;近两年AR眼镜也在逐渐升温&#xff0c;成为了创…

day17_异常

今日内容 零、 复习昨日 一、作业 二、异常 三、自定义异常 零、 复习昨日 见晨考,重点是String类的方法 StringBuffer和StringBuiler面试问 日期解析和格式化 int i Integer.parseInt(“111”); 一、作业 略,见答案二、异常 2.1 介绍 异常,就是程序出现的不正常的情况. 2.2…

RPA流程自动化技术在金融机构的落地方案详解

金融机构在面向数字化运营的转型过程中&#xff0c;需将智能流程自动化技术整合到数字化转型战略中&#xff0c;规划建设统一的企业流程自动化处理平台&#xff0c;作为数字化运营的辅助支撑类系统&#xff0c;明确流程治理方法和运营模式&#xff0c;确保足够的规模弹性&#…

【深度学习】Softmax回归及前馈神经网络

1 实验内容简介 1.1 实验目的 &#xff08;1&#xff09;熟练掌握tensor相关各种操作&#xff1b; &#xff08;2&#xff09;掌握广义线性回归模型&#xff08;logistic模型、sofmax模型&#xff09;、前馈神经网络模型的原理&#xff1b; &#xff08;3&#xff09;熟练掌…

第一章: uniapp引入axios异步框架

第一章&#xff1a; uniapp引入axios异步框架 在学习uniapp的过程中&#xff0c;发现uniapp框架默认集成request请求框架存在问题&#xff0c;发送请求时在header中塞入token值&#xff0c;而后台接收不到&#xff0c;也就是说uniapp默认的request请求框架&#xff0c;不支持在…

巨烽数字化采购项目启动,甄云助力医疗影像显示领军企业数智化升级

近日&#xff0c;医疗影像显示行业的领军者深圳市巨烽显示科技有限公司&#xff08;以下简称“巨烽”&#xff09;联合甄云科技举办数字化采购管理项目启动会&#xff0c;双方相关部门负责人及项目组成员参加了此次会议。 会上&#xff0c;就巨烽的数字化采购管理系统建设升级…

AI写作机器人-ai文章生成器在线

使用AI续写生成器&#xff0c;让内容创作事半功倍&#xff01; 随着人工智能技术的不断进步和应用&#xff0c;AI续写生成器的出现为内容创作带来了全新的革命。这种技术可以让你的写作事半功倍&#xff0c;让你轻松生成高质量的文章和内容。在这篇文章中&#xff0c;我们将介绍…

如何伪原创-自媒体伪原创软件

批量文字伪原创的作用 批量文字伪原创是指通过对原文进行修改、改写、调整等方式&#xff0c;生成大量新的类似原文的文本。其作用主要包括以下几个方面&#xff1a; 提高文本的独创性&#xff1a;批量伪原创可以有效地避免大量相似内容的出现&#xff0c;从而提高文本的独创性…

我如何学习使用 Jetpack Compose 开发 Android 应用程序

我如何学习使用 Jetpack Compose 开发 Android 应用程序 Jetpack Compose 和 Android 开发简介 2021 年 7 月&#xff0c;Google 发布了用于为 Android 应用构建原生 UI 的全新工具包 1.0 版。Jetpack Compose 是 Android 开发人员的游戏规则改变者&#xff0c;因为它从通过 X…

C#如何解决项目打开问题 error : 找不到指定的 SDK“Microsoft.NET.Sdk.WindowsDesktop”

错误提示&#xff0c;问题描述 后来发现&#xff0c;直接安装rider还是不能解决解决&#xff08;会自动配置关联&#xff08;path等&#xff09;&#xff0c;甚至自动下载的&#xff0c;官方的visual studio反而不会&#xff0c;之后再详细看怎么弄了&#xff09; VS2022项目…

IDEA 用上这款免费 GPT4 插件,生产力爆表了

大家好&#xff0c;我是一航&#xff01; 早前给大家分享过GPT的一些玩法&#xff0c;但是依旧有很多铁子没有掌握魔法的奥秘&#xff0c;始终没有用上&#xff1b;前两天&#xff0c;一兄台分享给我一款 IDE 插件&#xff1a;Bito-ChatGPT &#xff0c;安装就能直接在IDE中使…