算法复盘——LeetCode hot100:哈希

news2024/12/23 9:58:28

文章目录

  • 哈希表
    • 哈希表的基本概念
    • 哈希表的使用
        • 1. 插入操作
        • 2. 查找操作
        • 3. 删除操作
    • 哈希表的优点和缺点
    • 1.两数之和
      • 复盘
    • 242.有效的字母异位词
      • 复盘
    • 49.字母异位词分组
      • 复盘
    • 128. 最长连续序列
      • 复盘
      • HashSet

哈希表

先来搞清楚什么是哈希表吧~ 概念不清楚方法不清楚怎么做题捏

哈希表(Hash Table),也被称为散列表,是一种使用哈希函数组织数据,以支持快速插入和搜索的数据结构。它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数称为哈希函数,存放记录的数组称为哈希表。

哈希表的基本概念

  1. 哈希函数(Hash Function)
    哈希函数是一个将任意长度的输入(通常称为“关键码”或“键”)通过某种算法变换成固定长度的输出(通常是一个整数)的函数。理想的哈希函数应该能够均匀地、随机地将输入映射到输出范围上,以减少哈希冲突。
  2. 哈希表(Hash Table)
    哈希表是一种数据结构,用于存储键值对(key-value pairs)。它通过哈希函数将键映射到表中的一个位置来存储和访问数据。哈希表可以快速地插入、删除和查找数据项,时间复杂度通常接近O(1)。
  3. 哈希冲突(Hash Collision)
    由于哈希函数的输出范围有限,而输入范围是无限的,因此有可能出现两个或多个不同的输入映射到哈希表的同一位置的情况,这就是哈希冲突。处理哈希冲突的方法有多种,如开放寻址法(open addressing)和链地址法(chaining)。

哈希表的使用

1. 插入操作
  • 计算哈希值:使用哈希函数对键进行哈希运算,得到哈希值。
  • 处理哈希冲突:如果哈希值对应的位置已经被占用,则根据采用的冲突解决策略(如链地址法中的链表插入,或开放寻址法中的线性探测等)来处理冲突。
  • 存储键值对:将键值对存储在哈希表中计算出的位置。
2. 查找操作
  • 计算哈希值:与插入操作相同,首先使用哈希函数计算键的哈希值。
  • 处理哈希冲突:如果哈希值对应的位置有多个键值对(如链地址法中的链表),则遍历这些键值对,直到找到匹配的键或遍历完所有键值对。
  • 返回结果:如果找到匹配的键,则返回对应的值;否则,返回未找到。
3. 删除操作
  • 计算哈希值:与插入和查找操作相同,首先计算键的哈希值。
  • 处理哈希冲突:根据哈希值找到对应的位置,然后按照哈希表的冲突解决策略找到具体的键值对。
  • 删除键值对:从哈希表中删除找到的键值对。

哈希表的优点和缺点

优点

  • 查找效率高:在理想情况下,哈希表的查找、插入和删除操作的时间复杂度都接近O(1)。
  • 空间效率高:相对于其他数据结构,哈希表通常能以较小的空间存储相同数量的元素。

缺点

  • 哈希冲突:哈希冲突是哈希表的一个固有问题,它可能导致查找、插入和删除操作的时间复杂度增加。
  • 对哈希函数的依赖:哈希表的性能高度依赖于哈希函数的质量。一个设计不好的哈希函数可能导致哈希冲突频繁发生,从而降低哈希表的性能。
  • 动态扩容:当哈希表中的元素数量超过一定阈值时,需要动态扩容以维持良好的性能。扩容操作通常比较耗时,并可能导致重新计算所有元素的哈希值。

在这里插入图片描述

1.两数之和

1. 两数之和

  • 暴力解法直接开敲

    …解法略

  • 使用哈希表

class Solution {
    public int[] twoSum(int[] nums, int target) {
        // 维护 val -> index 的映射
        HashMap<Integer, Integer> valToIndex = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            // 查表,看看是否有能和 nums[i] 凑出 target 的元素
            int need = target - nums[i];
            if (valToIndex.containsKey(need)) {
                return new int[]{valToIndex.get(need), i};
            }
            // 存入 val -> index 的映射
            valToIndex.put(nums[i], i);
        }
        return null;
    }
}

复盘

关键点

  • 哪个是键,哪个是值

在这个twoSum方法中,HashMap<Integer, Integer>valToIndex用于存储数组中元素的值(nums[i])到其索引(i)的映射。这里,键(Key)是数组中的元素值(Integer类型),而值(Value)是该元素值在数组中的索引(也是Integer类型)。

  • 为什么这样放?

效率:使用哈希表(HashMap)来存储这种映射关系可以极大地提高查找效率。在遍历数组时,对于每个元素,我们都可以立即通过哈希表检查是否存在一个与之相加等于目标值target的另一个元素。如果存在,我们可以立即返回这两个元素的索引,而不需要继续遍历数组。

  1. 空间换时间:虽然这种方法使用了额外的空间来存储映射关系,但它显著减少了时间复杂度。如果不使用哈希表,我们可能需要使用两层循环来遍历数组,寻找满足条件的两个数,这会导致时间复杂度为O(n^2)。而使用哈希表后,时间复杂度可以降低到O(n)。
  2. 方便性:将值作为键,索引作为值,使得在找到满足条件的值时,我们可以直接通过哈希表获取到该值在数组中的索引,从而方便地构造出结果数组。

示例

假设我们有数组nums = [2, 7, 11, 15]和目标值target = 9

  • 当遍历到nums[0] = 2时,我们计算need = 9 - 2 = 7,然后检查哈希表中是否包含键7。此时不包含,所以我们将2和它的索引0存入哈希表。
  • 当遍历到nums[1] = 7时,我们计算need = 9 - 7 = 2,然后检查哈希表,发现已经存在键2,对应的值为0。这意味着我们找到了两个数27,它们的索引分别是01,它们的和等于target。因此,我们可以立即返回结果[0, 1]

通过这种方式,我们可以高效地解决“两数之和”问题。

  • 不能反过来设计键值对

在解决“两数之和”问题时,你不能简单地将索引作为键(Key)和数组中的值(Value)作为值(Value)在哈希表中反过来放,即不能创建HashMap<Integer, Integer>其中键是索引,值是数组中的元素值。这样做的主要原因是它不符合我们查找两个数使它们之和等于目标值的需求。

如果我们尝试将索引作为键,数组中的值作为值来存储,那么在遍历数组时,我们将无法有效地利用哈希表来快速查找是否存在与当前元素相加等于目标值的另一个元素。因为此时,哈希表并不能直接告诉我们哪个元素的值与当前元素相加等于目标值,而只能告诉我们某个值在数组中的位置。

然而,我们真正需要的是一种方式来快速查找是否存在一个数,它与当前遍历到的数相加等于目标值。这正是通过将数组中的值作为键,并将该值在数组中的索引作为值存储在哈希表中来实现的。这样,当我们遍历数组时,我们可以立即检查哈希表中是否存在一个与target - 当前值相等的键,如果存在,则说明我们找到了两个数,它们的和等于目标值。

因此,正确的做法是将数组中的值作为键(Key),并将该值在数组中的索引作为值(Value)存储在哈希表中,以便在遍历数组时能够快速查找和匹配。

  • 哈希表中的健是无序的吗?

哈希表中的键(Key)在大多数实现中是无序的。这种无序性主要源于哈希表的工作原理。

在Java中,HashMap是一个典型的无序哈希表实现,而LinkedHashMapTreeMap则提供了有序的哈希表实现。其中,LinkedHashMap按照插入顺序或访问顺序来维护键的顺序,而TreeMap则按照键的自然顺序或构造时提供的Comparator进行排序。这些有序哈希表实现为需要在保持键顺序的同时进行快速查找、插入和删除操作的应用场景提供了有力的支持。

242.有效的字母异位词

242. 有效的字母异位词

复盘

  • 快速定位字符串中的字母
  • 定义一个数组叫做record用来上记录字符串s里字符出现的次数

需要把字符映射到数组也就是哈希表的索引下标上,因为字符a到字符z的ASCII是26个连续的数值,所以字符a映射为下标0,相应的字符z映射为下标25。

再遍历 字符串s的时候,只需要将 s[i] - ‘a’ 所在的元素做+1 操作即可,并不需要记住字符a的ASCII,只要求出一个相对数值就可以了。 这样就将字符串s中字符出现的次数,统计出来了。

那看一下如何检查字符串t中是否出现了这些字符,同样在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再做-1的操作。

那么最后检查一下,record数组如果有的元素不为零0,说明字符串s和t一定是谁多了字符或者谁少了字符,return false。

  • 空间换时间
  • 错误记录:
    方法中一定要有对应的返回值,不要缺失返回语句

正确答案

class Solution {
    public boolean isAnagram(String s, String t) {
        int[] num = new int[26];
        if(s.length() != t.length()) return false;
        for(int i = 0;i < s.length(); i++){
                num[s.charAt(i) - 'a'] ++;
        }
        for(int j = 0;j < t.length();j++){
                num[t.charAt(j)-'a'] --; 
                if(num[t.charAt(j)-'a'] < 0){
                    return false;}
        }
        return true;
    }
}

优化思路

  • 先判断长度是否相等,不相等则直接false
  • 记录字符出现的次数
  • 记录数=-1时直接返回false

其他解法

  • 排序
    t 是 s 的异位词等价于「两个字符串排序后相等」。因此我们可以对字符串 s 和 t 分别排序,看排序后的字符串是否相等即可判断。此外,如果 s 和 t 的长度不同,t 必然不是 s 的异位词。
class Solution {
    public boolean isAnagram(String s, String t) {
        if (s.length() != t.length()) {
            return false;
        }
        char[] str1 = s.toCharArray();
        char[] str2 = t.toCharArray();
        Arrays.sort(str1);
        Arrays.sort(str2);
        return Arrays.equals(str1, str2);
    }
}

49.字母异位词分组

49. 字母异位词分组 - 力扣(LeetCode)

在这里插入图片描述

  • 每个排序后的字符串作为key,value为字符串数组的形式
  • 最后遍历哈希表,输出value

复盘

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<String,List<String>> hashMap = new HashMap<>();
        for(String s :strs){
            char[] tmp = s.toCharArray();
            Arrays.sort(tmp);
            String key  = new String(tmp);
            if(!hashMap.containsKey(key)){
                hashMap.put(key,new ArrayList());
            }
            hashMap.get(key).add(s);
        }
        return new ArrayList(hashMap.values());
        }
        }

注意细节:

  • 对于数组(如int[] nums),使用nums.length来访问长度。
  • 对于字符串(如String str),使用str.length()来调用方法获取长度(尽管它看起来像属性访问,但实际上是一个方法调用)。

错误复盘 细节大错特错,直接哭哭

  • 错误分析(错了好哇,错了好,错误能让人更快进步(其实很奔溃…))
  1. 错误的方法调用和属性访问

    • Array.sort(tmp); 应该是 Arrays.sort(tmp);。注意是 Arrays 而不是 Array,且是 sort 而不是 Sort
    • hashMap.containKey(key) 应该是 hashMap.containsKey(key)。注意是 containsKey 而不是 containKey
    • hashMap.putKey(key,new ArrayList[]);hashMap.getKey(key).add(s); 都是错误的。正确的方法是 hashMap.put(key, new ArrayList<String>())hashMap.get(key).add(s)
  2. 类型声明错误

    • new ArrayList[] 是不合法的。应该使用 new ArrayList<String>() 来创建一个新的 ArrayList 实例。
  3. 逻辑错误

    • 最后的 for(new ArrayList[] m: hashMap) {...} 循环完全不正确。hashMap 是一个 HashMap,而不是 ArrayList 数组。您可能想遍历 hashMap.values() 集合,但在这个上下文中,您并不需要这个循环,因为您只是要返回整个 HashMap 的值。
    • return hashMap.getValues(); 应该是 return new ArrayList<>(hashMap.values());。但在这个上下文中,您应该直接返回 hashMap.values() 的一个列表表示,但请注意 values() 返回的是 Collection<List<String>>,所以您可能需要将其转换为 List<List<String>>

反思:基础不扎实 什么是ArrayList 我竟然搞不清

是 Java 中的一个类,它属于 Java 集合框架(Java Collections Framework)的一部分。ArrayList 是一个基于动态数组实现的列表(List),它可以包含重复的元素,并且允许根据索引快速访问、插入和删除元素。

  • 主要特点
  1. 动态数组ArrayList 内部使用一个动态增长的数组来存储元素。当元素数量超过当前数组容量时,ArrayList 会自动创建一个更大的数组,并将旧数组中的元素复制到新数组中,以便能够继续添加更多元素。
  2. 有序集合ArrayList 维护了元素的插入顺序,即元素是按照它们被添加到列表中的顺序存储的。
  3. 允许重复元素:与 HashSet 不同,ArrayList 允许存储重复的元素。
  4. 非同步ArrayList 不是同步的。如果多个线程同时访问一个 ArrayList 实例,并且至少有一个线程从结构上修改了列表,那么它必须保持外部同步。
  5. 随机访问ArrayList 提供了对列表中元素的随机访问,即可以通过索引直接访问任何位置的元素,这使得 ArrayList 在需要频繁访问列表元素时非常高效。
  • 常用方法
  • boolean add(E e): 将指定的元素添加到此列表的末尾。
  • E remove(int index): 移除此列表中指定位置上的元素。
  • E get(int index): 返回列表中指定位置的元素。
  • int size(): 返回列表中的元素数。
  • void clear(): 移除此列表中的所有元素。
  • boolean contains(Object o): 如果此列表包含指定的元素,则返回 true
  • 示例
import java.util.ArrayList;  
  
public class Main {  
    public static void main(String[] args) {  
        ArrayList<String> list = new ArrayList<>();  
          
        // 添加元素  
        list.add("Apple");  
        list.add("Banana");  
        list.add("Cherry");  
          
        // 访问元素  
        System.out.println(list.get(1)); // 输出: Banana  
          
        // 移除元素  
        list.remove(0); // 移除索引为0的元素,即"Apple"  
          
        // 遍历列表  
        for (String fruit : list) {  
            System.out.println(fruit);  
        }  
          
        // 获取列表大小  
        System.out.println(list.size()); // 输出: 2  
    }  
}

128. 最长连续序列

128. 最长连续序列 - 力扣(LeetCode)

复盘

  • 要求时间复杂度为 O(n)

整数数组的排序时间复杂度取决于所使用的排序算法。不同的排序算法具有不同的时间复杂度,这主要取决于数组的大小(n)以及数组的初始状态(例如,是否已部分排序)。以下是一些常见排序算法及其时间复杂度的概述:

  1. 冒泡排序(Bubble Sort)
    • 平均时间复杂度:O(n^2)
    • 最坏时间复杂度:O(n^2)
    • 最好时间复杂度:O(n)(当数组已经是有序的时)
  2. 选择排序(Selection Sort)
    • 平均时间复杂度:O(n^2)
    • 最坏时间复杂度:O(n^2)
    • 最好时间复杂度:O(n^2)(与数组初始状态无关)
  3. 插入排序(Insertion Sort)
    • 平均时间复杂度:O(n^2)
    • 最坏时间复杂度:O(n^2)
    • 最好时间复杂度:O(n)(当数组已经是有序的时)
    • 插入排序对于小数组或部分有序的大数组表现良好。
  4. 希尔排序(Shell Sort)
    • 平均时间复杂度:取决于间隙序列,但通常认为是O(nlog2n)到O(n2)之间
    • 希尔排序是插入排序的一种更高效的改进版本,通过允许交换距离较远的元素来工作。
  5. 快速排序(Quick Sort)
    • 平均时间复杂度:O(nlogn)
    • 最坏时间复杂度:O(n^2)(但在实际应用中,通过随机化或三数取中法等方法可以大大降低出现最坏情况的可能性)
    • 快速排序是一种分治算法,通常被认为是实际应用中性能最好的排序算法之一。
  6. 归并排序(Merge Sort)
    • 平均时间复杂度:O(nlogn)
    • 最坏时间复杂度:O(nlogn)
    • 归并排序也是一种分治算法,它将数组分成两半,递归地对它们进行排序,然后将结果合并在一起。
  7. 堆排序(Heap Sort)
    • 平均时间复杂度:O(nlogn)
    • 最坏时间复杂度:O(nlogn)
    • 堆排序利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或者大于)它的父节点。

所以不能排序

  • 整数包括正整数、负整数、0 不能用数组模拟哈希表,用容器
  • 使用hashset

HashSet

HashMapHashSet 是 Java 集合框架中的两个非常重要的类,它们各自有独特的用途和内部实现机制。尽管它们在某些方面相似(比如都不保证元素的顺序,并且都允许存储 null 值),但它们在设计和用途上存在显著的区别。

  1. 底层实现
  • HashMap:基于哈希表的 Map 接口的实现。它存储键值对(key-value pairs),允许使用键(key)来快速查找、更新或删除对应的值(value)。HashMap 允许一个 null 键和多个 null 值。
  • HashSet:基于 HashMap 实现的 Set 接口。它不允许重复元素,但允许 null 元素。HashSet 实际上是通过在内部维护一个 HashMap 来实现的,其中所有的键(key)都是 HashSet 中的元素,而所有的值(value)都是相同的一个虚拟值(通常是 HashMap 的一个静态常量)。
  1. 用途
  • HashMap:当你需要存储键值对,并且能够通过键快速访问值时,使用 HashMap。例如,存储用户ID到用户信息的映射。
  • HashSet:当你只需要存储不重复的元素,而不需要关心它们的顺序时,使用 HashSet。例如,存储一个不重复的字符串集合。
  1. 性能
  • 两者在查找、插入和删除操作上的性能通常是常数时间(O(1)),但这取决于哈希函数的效率和哈希表的负载因子。
  • 由于 HashSet 内部是通过 HashMap 实现的,所以 HashSet 的性能特性与 HashMap 相似。
  1. 迭代顺序
  • HashMapHashSet 都不保证迭代顺序。这意味着,当你遍历它们时,元素的顺序可能与它们被添加的顺序不同,并且这个顺序在不同的 Java 实现或不同的 JVM 运行时环境中可能有所不同。
  1. 线程安全性
  • HashMapHashSet 都不是线程安全的。如果需要在多线程环境中使用它们,需要外部同步或使用线程安全的替代方案,如 ConcurrentHashMapCopyOnWriteArraySet

总结

HashMapHashSet 的主要区别在于它们的用途和内部实现。HashMap 用于存储键值对,而 HashSet 用于存储不重复的元素。尽管 HashSet 内部是通过 HashMap 实现的,但它们在 Java 集合框架中扮演着不同的角色,并且应根据具体需求选择使用。

  • 错误思路
  • 记录每个整数 键 为相对 值 但是整数的范围很大?不是26个字母。走不通。
  • 遍历数组,需要 比该数<1的值,存为键,遍历得整数判断 有键相等 说明该数被需要 ,新建数组放该数 最后+1,因为第一个数没有被放进数组 大错特错
    怎么算最长 Math.max(int1,int2)
class Solution {
    public int longestConsecutive(int[] nums) {
        HashSet<Integer> need = new HashSet<>();
        for(int i = 0;i < nums.length; i++){
            need.add(nums[i]+1);
            if(need.contains(nums[i])){
                int[] arr = new 
                return new int[] arr.add(nums[i])
            }
        }
        return  max arr.length + 1;
    }
}

试图使用 HashSet 来跟踪某些值,但并不符合解决问题的最佳方法。HashSet 通常用于检查元素是否存在,而不是用于存储需要连续增加的序列。

正确思路是:

  1. 使用 HashSet 来存储数组中的所有数字,以便快速检查某个数字是否存在。
  2. 遍历数组中的每个数字 num,对于每个 num,检查 num-1 是否存在于 HashSet 中。如果不存在(即 num 是序列的起始点),则从 num 开始,向两边扩展,直到找到不连续的数字,记录这个序列的长度。
  3. 跟踪并更新找到的最长连续序列的长度。
  • 正确答案
class Solution {
    public int longestConsecutive(int[] nums) {
        HashSet<Integer> need = new HashSet<>();
        for(int i = 0;i < nums.length; i++){
            need.add(nums[i]);
        
        }
        int res = 0;
        for(int i = 0;i < nums.length; i++){
            if(!need.contains(nums[i]-1)){
               int cur = nums[i];
               int length = 1;
               while(need.contains(cur+1)){//②
                cur = cur + 1;
                length += 1;
               }
               res = Math.max(res,length);
            }
    }
    return res;
}
}
  • 错误记录

  • 泛型<>里不能是基本类型

  • 在寻找最长连续序列的问题中,使用 ②cur 变量是必要的,原因有以下几点:

    1. 避免修改原始索引:在遍历数组 nums 时,我们通常使用索引 i 来访问数组中的元素。然而,如果我们试图在内部循环中直接修改 i 或使用 nums[i] 来追踪当前正在检查的连续序列的下一个数字,那么我们将无法正确地遍历整个数组,因为 i 的值会被意外地改变或 nums[i] 总是指向数组中的同一个位置。使用 cur 变量可以让我们独立地追踪当前正在检查的数字,而不影响数组的遍历过程。
    2. 追踪连续序列的下一个数字:在内部循环中,我们需要递增地检查连续序列中的下一个数字。由于我们不能直接修改 nums[i](它指向数组中的一个固定位置),我们需要一个变量(如 cur)来存储当前正在检查的数字,并在每次迭代时递增它。这样,我们就可以继续检查 cur + 1 是否存在于哈希集合中,从而确定连续序列的长度。
    3. 保持代码的清晰性和可维护性:使用 cur 变量可以使代码更加清晰和易于理解。它明确地表示了当前正在处理的数字,并且与数组的遍历索引 i 分开,从而避免了潜在的混淆和错误。
    4. 适应算法逻辑:在这个特定的问题中,算法的逻辑要求我们找到每个可能的连续序列的起点(即不是某个较大数字的前一个数字的数字),并从该起点开始递增地检查连续序列的长度。使用 cur 变量是实现这一逻辑的关键步骤之一。

    综上所述,使用 cur 变量是寻找最长连续序列问题中的一个重要且必要的步骤,它有助于我们正确地遍历数组、追踪连续序列的下一个数字,并保持代码的清晰性和可维护性。
    注意理清多层循环的逻辑,什么时候return

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

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

相关文章

MongonDB-索引

一、索引-index (一) 概述 索引支持在MongoDB中高效地执行查询。如果没有索引&#xff0c;MongoDB必须执行全集合扫描&#xff0c;即扫描集合中的每个文档&#xff0c;以选择与查询语句匹配的文档。这种扫描全集合的查询效率是非常低的&#xff0c;特别在处理大量的数据时&am…

firewalld 防火墙常用命令,新手必看

firewalld 防火墙常用命令 防火墙状态命令 systemctl start firewalld #启动防火墙 systemctl stop firewalld #关闭防火墙 systemctl restart firewalld #重启防火墙 systemctl enable firewalld #设置开机自启 systemctl disable firewalld #禁用开机自启 systemctl s…

自己开发完整项目一、登录功能-03(使用springSecurity安全框架,查询用户角色权限)

一、说明 在前面两章节&#xff0c;实现了通过springsecurity来进行用的登录认证&#xff0c;当用户输入用户名和密码之后&#xff0c;通过额数据库中的信息比对&#xff0c;比对成功那么放行。但是还存在一个问题&#xff1a;因为系统的所有页面包括按钮都是有各自的权限&…

全网最全robotframework自动化测试环境搭建

一、前言 1、在2019年之前&#xff0c;robotframework-ride的版本一直是1.5.2.1&#xff0c;是2016年1月份的版本&#xff0c;只能安装在python2.7的环境上&#xff0c;导致如果想同时使用robotframework做测试且又需要python3环境编写python代码的小伙伴都需要在操作系统上安…

Golang 读取文件

GoLang读取文件需要用到os类去打开文件&#xff0c;然后再用其他方式分析文件里的内容。打开文件比较简单&#xff0c;使用os.Open就可以了&#xff0c;记住用defer关闭就行。但是读取文件内容就头疼了&#xff0c;以文本文件为例子&#xff0c;就有各种方式 读取到byte数组 首…

渐进式衰老?医美三剑客的“市梦率”幻灭了

医美股神话彻底幻灭了。 从股价蒸发到业绩失速&#xff0c;“医美三剑客”上演着繁华落幕&#xff0c;回归平凡的剧本。 近一年来&#xff0c;爱美客、华熙生物、昊海生科股价分别累计下跌52.97%、46.03%、16.09%。 “医美三剑客”近一年累计跌幅&#xff08;资料来源&#x…

分水岭算法简介

分水岭算法是一种经典的图像分割技术&#xff0c;广泛应用于图像处理领域。它的名称源自地理学中的“分水岭”概念&#xff0c;即在地形中&#xff0c;水从高处流向低处&#xff0c;最终汇聚成河流的过程。在图像分割中&#xff0c;分水岭算法将灰度图像视为地形&#xff0c;将…

STM32(八):定时器——输入捕获实验

目录 输入捕获模式测频率&#xff1a; 结构图&#xff1a; 步骤&#xff1a; 部分函数详解&#xff1a; 源码&#xff1a; PWMI模式测频率占空比&#xff1a; 结构图&#xff1a; ​编辑 举例说明 源码&#xff1a; 输入捕获模式测频率&#xff1a; 结构图&#xf…

using showdown js with openAi streaming response

题意&#xff1a;"使用 Showdown.js 处理 OpenAI 流式响应" 问题背景&#xff1a; I tried using showdownjs to translate streamed markdown from OpenAi to HTML "我尝试使用 Showdown.js 将来自 OpenAI 的流式 Markdown 转换为 HTML" I changed the …

机器学习第五十四周周报 MAGNA

文章目录 week54 MAGNA摘要Abstract一、文献阅读1. 题目2. Abstract3. 文献解读3.1 Introduce3.2 创新点 4. MAGNA4.1 基础4.2 多跳注意力扩散机制4.3 网络架构4.4 图注意力扩散机制的分析 5. 实验分析5.1 节点分类5.2 知识图谱 6.结论 二、若依系统1. 权限管理2. 数据字典3. 其…

【Linux修行路】进程通信——共享内存

目录 ⛳️推荐 一、直接原理 1.1 共享内存的的申请 1.2 共享内存的释放 二、代码演示 2.1 shmget 2.1.1 详谈key——ftok 2.2 创建共享内存样例代码 2.3 获取共享内存——进一步封装 2.4 共享内存挂接——shmat 2.5 共享内存去关联——shmdt 2.6 释放共享内存——s…

gitee版本控制

前置要求&#xff1a; 安装Git git下载地址&#xff1a;https://git-scm.com/download/win 注册gitee gitee官网&#xff1a;Gitee - 基于 Git 的代码托管和研发协作平台 创建普通项目 目录 git推送远程仓库基本操作 克隆仓库到本地 项目上传 版本管理 分支管理版本…

紧急 浮毛正在挑战免疫系统?推荐榜TOP3浮毛空气净化器使用体验

作为一名多猫家庭的铲屎官&#xff0c;出门路人必知道我养猫&#xff0c;不是把铲屎官三个字大大的打在我脑门上了。而是衣服、裤子上无处不在的猫毛&#xff0c;以前我就靠着人力与各种工具与猫毛斗争&#xff0c;但效果总是差强人意。直到有一天&#xff0c;我因忽视浮毛而患…

Linux 用户缓冲区

1. 文件描述符的分配规则 我们知道Linux进程默认情况下会有3个缺省打开的文件描述符&#xff0c;分别是标准输入stdin--0&#xff0c; 标准输出stdout--1&#xff0c; 标准错误stderr--2。0,1,2对应的物理设备一般是&#xff1a;键盘&#xff0c;显示器&#xff0c;显示器.接下…

字符串原始字面量

简介&#xff1a;C11中添加定义了原始字符串的字面量&#xff0c;定义方式为&#xff1a;R"xxx(原始字符串)xxx",其中&#xff08;&#xff09;两边的字符串可以省略。原始字面量R可以直接表示字符串的实际含义&#xff0c;而不需要额外对字符串做转译或链接等操作 …

ddpm和ddim小记

前面分析了DDPM和DDIM&#xff0c;但是仍然感觉对其理解不是和透彻&#xff0c;最近又学习了下&#xff0c;简单记录一下进一步的理解。为了方便理解&#xff0c;这里直接以两个像素的灰度图像为例。前面讲过无论是DDPM还是DDIM&#xff0c;他们的训练过程都是一样的&#xff0…

一套采用JAVA语言开发的数字化产科管理平台源码,自主知识产权,三甲综合医院应用案例,系统稳定运行,全套源码交付。

一套采用JAVA语言开发的一套数字化产科管理平台源码&#xff0c;自主知识产权&#xff0c;三甲综合医院应用案例&#xff0c;系统稳定运行。全套源码交付。 数字化产科管理平台源码技术栈&#xff1a; 技术架构&#xff1a;前后端分离 开发语言&#xff1a;Java 开发工具…

深度学习基础--梯度下降与初始化

在神经网络的背景下&#xff0c;它们用于寻找能够最小化损失函数的参数&#xff0c;使模型能够根据输入准确预测训练数据的输出。基本方法是随机选择一组初始参数&#xff0c;然后逐步进行微小调整&#xff0c;平均而言这些调整会降低损失。每一次的调整都是基于当前参数位置对…

ERROR: Cannot uninstall numpy 1.24.2, RECORD file not found.

目录 1.问题描述&#xff1a;2.解决方法&#xff1a;2.1流程2.2结果 小结&#xff1a; 1.问题描述&#xff1a; 卸载 numpy 时报错&#xff1a; ERROR: Cannot uninstall numpy 1.24.2, RECORD file not found. You might be able to recover from this via: pip install --f…

HTB-sequal(mysql)

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天给大家讲解sequal这台靶机 渗透过程 信息搜集 服务器开放了3306mysql端口思路&#xff1a;mysql爆破-sC参数会执行 相关的默认脚本 连接mysql数据库 通过空密码连接道mysql数据库flag&#xff1a;7b4bec00d1a39…