【动态规划】NK刷题之DP7 连续子数组的最大乘积

news2024/11/30 14:46:09

【动态规划】NK刷题之DP7 连续子数组的最大乘积

  • 1.题目
  • 2.题解
  • 3.代码部分
    • 法一:动态规划
      • 3.1.1 创建变量n,并读入数据
      • 3.1.2 创建动态数组,并初始化
      • 3.1.3 对动态数组断言
      • 3.1.4 读入原整形数组的数据
      • 3.1.5 创建变量ret,并赋初值
      • 3.1.6 循环实现关键递推式部分
      • 3.1.7 C语言完整代码
      • 3.1.7 优化代码
    • 3.2 法二:分治
      • 3.2.1 基本思路
      • 3.2.2 创建临时变量n,并读入数据
      • 3.2.3 把数据读入动态数组a中
      • 3.2.4 创建临时变量ret,sum,left,right,v,并赋初值
      • 3.2.5 循环实现求所有可能的连续子数组乘积最大值,并用ret变量维护一个最大的
      • 3.2.6 创建函数max_product求某一段有负数连续数组的乘积最大值
        • 3.2.8 释放动态数组内存,并打印最大值
        • 3.2.7 C语言完整代码
        • 3.2.8 优化
  • 4.总结与感悟

❤️博客主页: 小镇敲码人
🍏 欢迎关注:👍点赞 👂🏽留言 😍收藏
🌞在一切变好之前,我们总要经历一些不开心的日子,这段日子也许很长,也许只是一觉醒来。有时候,选择快乐,更需要勇气。
🍉 如果你也迷失在了路上,对人生充满了迷惘,不要害怕,冷静下来,慢慢的自救,不断求知,让自己变得更加优秀吧!!!


1.题目

  • 牛客网上面的题我们先给出链接,有需要的朋友可以点击下面链接去做一下点击此处跳转

输入一个长度为 n 的整型数组 nums,数组中的一个或连续多个整数组成一个子数组。求所有子数组的乘积的最大值。

  1. 子数组是连续的,且最小长度为 1 ,最大长度为 n
  2. 长度为 1 的子数组,乘积视为其本身,比如 [4] 的乘积为 4
  3. 该题的数据保证最大的乘积不会超过 int的范围,即不
    超过232-1

2.题解

1.首先我们要知道这道题与【动态规划】NK刷题记之DP6 连续子数组最大和(C语言实现)的区别在于这道题多了负负得正的情况1,因此简单的只维护一个最大值已经达不到我们的要求了,那么我们就需要维护两个值,一个维护当前连续子数组的最大值,一个维护当前连续子数组的最小值。

  1. 问题来了,该如何维护这两个最大值和最小值呢?

    首先我们要创建两个动态数组dp1[i]dp2[i],用来保存当前位置连续子数组的最大值和最小值,可以知道 d p 1 [ i ] > = d p 2 [ i ] dp1[i] >= dp2[i] dp1[i]>=dp2[i] 1️⃣

    其次我们思考哪些值可以更新dp1呢,我们可以考虑所有可能的情况

    1. a [ i ] > 0 , d p 1 [ i − 1 ] > 0 a[i] > 0,dp1[i-1] > 0 a[i]>0,dp1[i1]>0,由1️⃣不能知道dp2[i-1]的正负,此时 d p 1 [ i ] = a [ i ] ∗ d p 1 [ i − 1 ] dp1[i] = a[i] * dp1[i-1] dp1[i]=a[i]dp1[i1],需要讨论dp2[i-1]的情况,才可以确定dp2[i-1]的表达式

    1.1   d p 2 [ i − 1 ] > 0 , d p 2 [ i ] = a [ i ] dp2[i-1] > 0,dp2[i] = a[i] dp2[i1]>0,dp2[i]=a[i]
    1.2   d p 2 [ i − 1 ] < = 0 , d p 2 [ i ] = d p 2 [ i − 1 ] ∗ a [ i ] dp2[i-1] <= 0,dp2[i] = dp2[i-1] * a[i] dp2[i1]<=0,dp2[i]=dp2[i1]a[i]

    1.   a [ i ] > 0 , d p 1 [ i − 1 ] < = 0 a[i] > 0 ,dp1[i-1] <= 0 a[i]>0,dp1[i1]<=0,由1️⃣可以知道 d p 2 [ i − 1 ] < = 0 dp2[i-1] <= 0 dp2[i1]<=0,此时 d p 1 [ i ] = a [ i ] , d p 2 [ i − 1 ] = d p 2 [ i − 1 ] ∗ a [ i ] dp1[i] = a[i],dp2[i-1] = dp2[i-1] * a[i] dp1[i]=a[i]dp2[i1]=dp2[i1]a[i]
    2.   a [ i ] < 0 , d p 1 [ i − 1 ] > 0 a[i] < 0,dp1[i-1] > 0 a[i]<0,dp1[i1]>0, 由1️⃣不能知道dp2[i-1]的正负,此时 d p 2 [ i − 1 ] = d p 1 [ i − 1 ] ∗ a [ i ] dp2[i-1] = dp1[i-1] * a[i] dp2[i1]=dp1[i1]a[i],要讨论dp2[i-1]的情况,才可以确定dp1[i-1]的表达式

    3.1   d p 2 [ i − 1 ] > 0 , d p 1 [ i ] = a [ i ] dp2[i-1]>0,dp1[i] = a[i] dp2[i1]>0,dp1[i]=a[i]
    3.2   d p 2 [ i − 1 ] < 0 , d p 1 [ i ] = d p 2 [ i − 1 ] ∗ a [ i ] dp2[i-1] < 0,dp1[i] = dp2[i-1] * a[i] dp2[i1]<0,dp1[i]=dp2[i1]a[i]

    1.    a [ i ] < 0 , d p 1 [ i − 1 ] < = 0 , 由 : o n e : 可以知道 d p 2 [ i − 1 ] < = 0 , 此时 d p 1 [ i ] = d p 2 [ i − 1 ] ∗ a [ i ] , d p 2 [ i ] = a [ i ] a[i] < 0,dp1[i-1] <= 0,由:one:可以知道dp2[i-1] <= 0,此时dp1[i] = dp2[i-1] * a[i],dp2[i] = a[i] a[i]<0,dp1[i1]<=0,:one:可以知道dp2[i1]<=0,此时dp1[i]=dp2[i1]a[i],dp2[i]=a[i]
      5.     a [ i ] = 0 , d p 1 [ i ] 与 d p 2 [ i ] 都为 0 a[i] = 0,dp1[i]与dp2[i]都为0 a[i]=0,dp1[i]dp2[i]都为0,代入哪个表达式均可

    通过上述推理我们知道了dp1[i]dp2[i]是如何更新的,我们可以把上述推理通过编程语言来表示出来,if语句可以实现,但是没必要,因为可以观察到,更新dp1[i],dp2[i]的表达式只有那么3个,即 d p 1 [ i − 1 ] ∗ a [ i ] dp1[i-1]*a[i] dp1[i1]a[i], d p 2 [ i − 1 ] ∗ a [ i ] dp2[i-1]*a[i] dp2[i1]a[i], a [ i ] a[i] a[i],所以我们在这三者里面取一个最大值和最小值就不需要繁琐的if语句判断了
             状态转移方程:
    d p 1 [ i ] = M a x ( d p 1 [ i − 1 ] ∗ a [ i ] , d p 2 [ i − 1 ] ∗ a [ i ] , a [ i ] ) dp1[i] = Max(dp1[i-1] * a[i],dp2[i-1] * a[i],a[i]) dp1[i]=Max(dp1[i1]a[i],dp2[i1]a[i],a[i])
    d p 2 [ 1 ] = M i n ( d p 1 [ i − 1 ] ∗ a [ i ] , d p 2 [ i − 1 ] ∗ a [ i ] , a [ i ] ) dp2[1] = Min(dp1[i-1] * a[i],dp2[i-1] * a[i],a[i]) dp2[1]=Min(dp1[i1]a[i],dp2[i1]a[i],a[i])
    我们创建临时变量ret来维护连续子数组的最大值,ret = max(ret,dp1[i])
    4. 有了递推式,就可以去循环求解了,进行代码实现了。

3.代码部分

法一:动态规划

3.1.1 创建变量n,并读入数据

 int n = 0;
 scanf("%d", &n);

3.1.2 创建动态数组,并初始化

    int* a = (int*)malloc(n * sizeof(int));//创建变量a,来读入原始数组
    /*dp1用来表示遍历到a[i]时连续子数组乘积的最大值,
    而dp2[i]用来表示遍历到a[i]时连续子数组乘积的最小值*/
    int* dp1 = (int*)malloc(n * sizeof(int));
    int* dp2 = (int*)malloc(n * sizeof(int));
    memset(a, 0, n * sizeof(int));
    memset(dp1, 0, n * sizeof(int));
    memset(dp2, 0, n * sizeof(int));

3.1.3 对动态数组断言

    assert(dp1 && dp2 && a);

3.1.4 读入原整形数组的数据

    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);

3.1.5 创建变量ret,并赋初值

    dp1[0] = a[0];
    dp1[0] = a[0];
    int ret = a[0];//创建ret变量,初始化ret,这里就考虑了n==1的情况

3.1.6 循环实现关键递推式部分

for(int i = 1; i < n; i++) {
	dp1[i] = Max(dp1[i - 1] * a[i], dp2[i - 1] * a[i], a[i]);
	dp2[i] = Min(dp1[i - 1] * a[i], dp2[i - 1] * a[i], a[i]);
	ret = Max1(ret, dp1[i]);//维护所有连续子数组乘积中的最大值
}

3.1.7 C语言完整代码

  • 注意这里纠正之前博客的一个错误,动态内存分配和释放必须对应,即有分配就必须有释放,不释放内存会产生“内存泄漏”,后果是随着程序运行多次,可以使用的内存空间越来越少;另一方面,再次释放已经释放的内存空间,会导致程序出现崩溃性错误
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
int Max1(int a, int b) {
    if (a > b)
        return a;
    return b;
}
void swap(int* a, int* b) {
    int t = *a;
    *a = *b;
    *b = t;
}
int Max(int a, int b, int c) {
    if (b > a)
        swap(&a, &b);
    if (c > a)
        swap(&c, &a);
    return a;
}
int Min(int a, int b, int c) {
    if (a > c)
        swap(&c, &a);
    if (a > b)
        swap(&a, &b);
    return a;
}
int main() {
    int n = 0;
    scanf("%d", &n);
    int* a = (int*)malloc(n * sizeof(int));//创建变量a,来读入原始数组
    /*dp1用来表示遍历到a[i]时连续子数组乘积的最大值,
    而dp2[i]用来表示遍历到a[i]时连续子数组乘积的最小值*/
    int* dp1 = (int*)malloc(n * sizeof(int));
    int* dp2 = (int*)malloc(n * sizeof(int));
    /*
    进行动态数组的初始化和断言,防止出现空指针的情况
  */
    memset(a, 0, n * sizeof(int));
    memset(dp1, 0, n * sizeof(int));
    memset(dp2, 0, n * sizeof(int));
    assert(dp1 && dp2 && a);
    /*读入数据*/
    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    dp1[0] = a[0];
    dp1[0] = a[0];
    int ret = a[0];//创建ret变量,初始化ret,这里就考虑了n==1的情况
    for (int i = 1; i < n; i++) {
        dp1[i] = Max(dp1[i - 1] * a[i], dp2[i - 1] * a[i], a[i]);
        dp2[i] = Min(dp1[i - 1] * a[i], dp2[i - 1] * a[i], a[i]);
        ret = Max1(ret, dp1[i]);//维护所有连续子数组乘积中的最大值
    }
    free(dp1 && dp2 && a);//释放分配的内存
    printf("%d", ret);打印连续数组乘积的最大值
}

3.1.7 优化代码

优化就是观察到每一次遍历都只需要用到dp1[i],dp1[i-1],dp2[i],dp2[i-1],把两个大的动态数组用4个临时变量来表示,节省了空间

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
int Max1(int a, int b) {
    if (a > b)
        return a;
    return b;
}
void swap(int* a, int* b) {
    int t = *a;
    *a = *b;
    *b = t;
}
int Max(int a, int b, int c) {
    if (b > a)
        swap(&a, &b);
    if (c > a)
        swap(&c, &a);
    return a;
}
int Min(int a, int b, int c) {
    if (a > c)
        swap(&c, &a);
    if (a > b)
        swap(&a, &b);
    return a;
}
int main() {
    int n = 0;
    scanf("%d", &n);
    int* a = (int*)malloc(n * sizeof(int));
    memset(a, 0, n * sizeof(int));
    assert(a);
    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    int MAX = a[0];
    int MIN = a[0];
    int ret = a[0];
    for (int i = 1; i < n; i++) {
        int MAXbefore = 0;
        int MINbefore = 0;
        MAXbefore = MAX;
        MINbefore = MIN;
        MAX = Max(MAXbefore* a[i], MINbefore * a[i], a[i]);
        MIN = Min(MAXbefore* a[i], MINbefore * a[i], a[i]);
        ret = Max1(ret, MAX);
    }
    free(a);
    printf("%d", ret);
}

3.2 法二:分治

3.2.1 基本思路

  • 将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。

    先考虑一种最简单的情况,没有0,该如何求连续子数组的最大值,很简单你可能会这样去做

    1. 创建一个临时变量sum,把循环把数组的乘积存入sum
    1. s u m > 0 sum > 0 sum>0,他就是这个连续子数组数组乘积的最大值
    2. s u m < 0 sum < 0 sum<0,这个时候如何得到连续子数组的乘积最大值呢?很简单我们把 s u m sum sum从前往后除以 a [ i ] a[i] a[i]直到得到一个正数停止,或者是把 s u m sum sum从后往前除直到得到一个正数停止,这样我们再从这两个数中取一个最大值就为连续子数组的乘积最大值了
    1. 那有0的时候该怎么办呢,也很简单,遍历到0停止,然后做一样的事情就行了
      当然这只是一个大体的思路还有很多细节需要去处理
    • 注意有0的情况相当于把一个大的数组分成了很多段小的连续子数组想要求这些连续子数组的乘积最大值,方法是一样的

    3.2.2 创建临时变量n,并读入数据

      int n = 0;
      scanf("%d", &n);//创建变量n,并读入数据
    
  #### 创建动态数组a和dp,并进行断言
  ```c
  /*创建动态数组a和dp,一个用来读入原始数组的数据,
    一个用来储存不同段连续子数组乘积的最大值*/
    int* a = (int*)malloc(n * sizeof(int));
    int* dp = (int*)malloc(n * sizeof(int));
     assert(dp && a);//断言,防止出现空指针的情况

3.2.3 把数据读入动态数组a中

 for(int i = 0; i < n; i++) //读入原始数组的数据
      scanf("%d", &a[i]);

3.2.4 创建临时变量ret,sum,left,right,v,并赋初值

  int v = 0;//创建临时变量,用来表示动态数组dp的下标
  int left = 0;//表示一段连续子数组的最左边下标
  int right = 0;//表示一段连续子数组的最右边下标
  int sum = a[0];//表示遍历到当前位置的连续子数组的乘积,注意a[i]如果等于0,sum就不会乘上这个a[i]

3.2.5 循环实现求所有可能的连续子数组乘积最大值,并用ret变量维护一个最大的

/*循环实现具体的算法*/
 for (int i = 1; i < n; i++) {
     if (a[i] == 0 || i == n-1) {
        //某一段可能没有0,
         //但是已经遍历到数组的最后了,我们需要考虑这种情况
          if(a[i]!= 0)
             sum *= a[i];
         right = i;
         //更新right的值,
         //是因为存在没有0的情况,如果不更新为i的话可能
         //会导致最后一个数据丢失而出bug,不能因小失大
         if (sum > 0 || left == right)   
          dp[v++] = sum;
         //left == right的情况是前面有0,
        //然后最后只剩下最后一个数据的情况,
        //很明显这一个数据的最大乘积就是它本身
         else if(right - left == 1 && a[i] == 0)
             dp[v++] = 0;
           //这个情况就是sum < 0
           //且这一小段只有2个数据的情况,一个负数和0,很明显乘积最大值应该是0
         else
             max_product(dp, a, left, right, sum, &v);
             //传入相应的值,计算这一小段的连续子数组乘积最大值
         left = right + 1;//left更新下一段子数组从不为0的开始
         sum = 1;//重置sum的值
         ret  = Max(ret, dp[v - 1]);//维护所有段连续子数组乘积的最大值
     }
     else
     {
         sum *= a[i];//没有遇见特殊情况正常数组相乘并存入sum中
     }
 }

3.2.6 创建函数max_product求某一段有负数连续数组的乘积最大值

void max_product(int* answer, int* a, int left, int right, int sum) {
 int sum1 = sum;
 for (int i = left; i <= right; i++) {
     if (a[i] == 0)
         continue;
     sum1 /= a[i];
     if (sum1 > 0)
         break;
 }
 for (int i = right; i >= left; i--) {
     if (a[i] == 0)
         continue;
     sum /= a[i];
     if (sum > 0)
         break;
 }
 *answer= Max(sum, sum1);
}

3.2.8 释放动态数组内存,并打印最大值

/*释放分配的
 动态数组的内存*/
 free(a);
 free(dp);
 printf("%d", ret);//打印不同段的连续子数组乘积的最大值

3.2.7 C语言完整代码

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
int Max(int a, int b) {
    if (a > b)
        return a;
    return b;
}
void max_product(int* dp, int* a, int left, int right, int sum, int* v) {
    int sum1 = sum;
    for (int i = left; i <= right; i++) {
        if (a[i] == 0)
            continue;
        sum1 /= a[i];
        if (sum1 > 0)
            break;
    }
    for (int i = right; i >= left; i--) {
        if (a[i] == 0)
            continue;
        sum /= a[i];
        if (sum > 0)
            break;
    }
    dp[(*v)++] = Max(sum, sum1);
}
int main() {
    int n = 0;
    scanf("%d", &n);//创建变量n,并读入数据
    /*创建动态数组a和dp,一个用来读入原始数组的数据,
    一个用来储存不同段连续子数组乘积的最大值*/
    int* a = (int*)malloc(n * sizeof(int));
    int* dp = (int*)malloc(n * sizeof(int));
     assert(dp && a);//断言,防止出现空指针的情况
     for (int i = 0; i < n; i++) //读入原始数组的数据
        scanf("%d", &a[i]);
    int v = 0;//创建临时变量,用来表示动态数组dp的下标
    int left = 0;//表示一段连续子数组的最左边下标
    int right = 0;//表示一段连续子数组的最右边下标
    int sum = a[0];//表示遍历到当前位置的连续数组的乘积,注意a[i]如果等于0,sum就不会乘上这个a[i]
    int ret = a[0];//创建一个临时变量来维
                     //护不同段连续子数组乘积最大值
    /*循环实现具体的算法*/
    for (int i = 1; i < n; i++) {
        if (a[i] == 0 || i == n-1) {
           //某一段可能没有0,
            //但是已经遍历到数组的最后了,我们需要考虑这种情况
             if(a[i]!= 0)
                sum *= a[i];
            right = i;
            //更新right的值,
            //是因为存在没有0的情况,如果不更新为i的话可能
            //会导致最后一个数据丢失而出bug,不能因小失大
            if (sum > 0 || left == right)   
             dp[v++] = sum;
            //left == right的情况是前面有0,
           //然后最后只剩下最后一个数据的情况,
           //很明显这一个数据的最大乘积就是它本身
            else if(right - left == 1 && a[i] == 0)
                dp[v++] = 0;
              //这个情况就是sum < 0
              //且这一小段只有2个数据的情况,一个负数和0,很明显乘积最大值应该是0
            else
                max_product(dp, a, left, right, sum, &v);
                //传入相应的值,计算这一小段的连续子数组乘积最大值
            left = right + 1;//left更新下一段子数组从不为0的开始
            sum = 1;//重置sum的值
            ret  = Max(ret, dp[v - 1]);//维护所有段连续子数组乘积的最大值
        }
        else
        {
            sum *= a[i];//没有遇见特殊情况正常数组相乘并存入sum中
        }
    }
    /*释放分配的
    动态数组的内存*/
    free(a);
    free(dp);
    printf("%d", ret);//打印不同段的连续子数组乘积的最大值
    return 0;
}

3.2.8 优化

同理这里的优化也是在空间上进行优化,每一次只用到了当前的dp[i],我们直接用临时变量来代替

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
int Max(int a, int b) {
    if (a > b)
        return a;
    return b;
}
void max_product(int* answer, int* a, int left, int right, int sum) {
    int sum1 = sum;
    for (int i = left; i <= right; i++) {
        if (a[i] == 0)
            continue;
        sum1 /= a[i];
        if (sum1 > 0)
            break;
    }
    for (int i = right; i >= left; i--) {
        if (a[i] == 0)
            continue;
        sum /= a[i];
        if (sum > 0)
            break;
    }
    *answer= Max(sum, sum1);
}
int main() {
    int n = 0;
    scanf("%d", &n);
    int* a = (int*)malloc(n * sizeof(int));
    for (int i = 0; i < n; i++) 
        scanf("%d", &a[i]);
    int left = 0;
    int right = 0;
    int sum = a[0];
    int ret = a[0];
    int  answer = 0;
    for (int i = 1; i < n; i++) {
        if (a[i] == 0 || i == n-1) {
            if(a[i]!= 0)
              sum *= a[i];
            right = i;
            if (sum > 0 || left == right)
                answer = sum;
            else if(right - left == 1 && a[i] == 0)
                answer = 0;
            else
                max_product(&answer, a, left, right, sum);
            left = right + 1;
            sum = 1;
            ret  = Max(ret, answer);
        }
        else
        {
            sum *= a[i];
        }
    }
    printf("%d", ret);
    return 0;
}

4.总结与感悟

     这个题虽然是中等难度的题目,但对我的帮助还是挺大,让我对分治和动态规划这两种算法又有了更深的理解,分治法和动态规划这两种方法都可以AC这道题,看自己更擅长哪一种吧,我更喜欢动态规划的简洁,因为分治要注意的细节还是挺多的,容易写出bug,最后关于这篇博客有什么问题和不足,欢迎大家在评论区告诉我哦😄😄.


  1. 在这里插入图片描述 ↩︎

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

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

相关文章

chatgpt赋能python:Python怎么下jieba库

Python怎么下jieba库 Python是目前最流行的动态编程语言之一&#xff0c;广泛应用于Web开发、数据分析、人工智能等领域。对于中文文本处理来说&#xff0c;jieba库是一款非常实用的工具。本文将介绍如何下载jieba库&#xff0c;并探讨其在中文分词、情感分析等方面的应用。 …

week7 表示学习(Representation Learning) Part1--Pretext Text

文章目录 Representation LearningInferring structure&#xff08;推断结构&#xff09; Transformation predictionRotation predictionRelative transformation prediction ReconstructionDenoising AutoencodersContext encodersColorizationSplit-brain encoders Instance…

Keras-3-实例3-回归问题

1. 回归问题 1.1 波士顿房价数据集加载: 预测20世界70年代中期波士顿郊区房屋价格的中位数。 已知当时郊区有一些数据点&#xff0c;如犯罪率、房产税率等。 与IMDB和路透社数据集相比&#xff0c;波士顿房价数据集样本量比较少&#xff0c;只有506个样本&#xff1b;同时&a…

数据结构——绪论/线性表

文章目录 **一 基本概念****二 算法和算法评价****三 线性表的定义和基本操作****四 线性表的顺序表示****1 定义****2 基本操作** **五 线性表的链式表示****1 单链表的定义****2 单链表的基本操作实现****3 双链表****4 循环链表****5 静态链表** 一 基本概念 数据类型&…

使用pycharm入门python的一些注意点

今儿在帮别人跑一段python代码&#xff0c;实际上我对python并不熟悉&#xff0c;只能边摸索边尝试。选择了pycharm这个工具。 一.怎么安装python使用的库文件 能用来安装python的库文件的&#xff0c;有很多种办法&#xff0c;这里只介绍pip和pip3。因为pip和pip3的优势是能…

SpringCloud第一篇:服务的注册与发现Eureka

一、spring cloud简介 spring cloud 为开发人员提供了快速构建分布式系统的一些工具&#xff0c;包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等。它运行环境简单&#xff0c;可以在开发人员的电脑上跑。 二、创建服务注册中心 …

oracle细节、经验锦集

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/131054454 出自【进步*于辰的博客】> 由于是随兴记录&#xff0c;因此阐述的比较多而乱&…

详解Eureka服务注册和调用

目录 1.概述 2.环境 2.1.项目结构 2.2.项目架构 2.3.依赖 3.注册中心 3.1.配置使用 3.2.管理页 3.3.集群 4.服务注册 5.服务调用 5.2.Ribbon 5.3.Feign 5.4.OpenFeign 1.概述 我们把从外部进入到微服务集群里的流量称为“南北流量”、微服务集群节点间流转的流量…

HTML type=“radio“ 不显示按钮

问题 HTML中type&#xff1d;"radio" 但是在界面中不显示按钮。 详细问题 HTML中type&#xff1d;"radio" 但是在界面中不显示按钮。 笔者html核心代码 <div>性别<input type"radio" id"male" name"gender" va…

chatgpt赋能python:Python中的中文分词神器——jieba

Python中的中文分词神器——jieba 介绍 如果你曾经在处理中文文本时&#xff0c;也许会遇到中文分词的需求&#xff0c;jieba就是一款不可错过的工具。 jieba 是目前最好的 Python 中文分词库&#xff0c;它具有高效、简单和可定制等优点&#xff0c;适合各种规模的文本分词…

Linux学习之vim四种模式初探

vim是一个多模式&#xff0c;有vim /所在目录/文件名&#xff0c;若是已经有了文件&#xff0c;可以打开文件进行编辑&#xff0c;若是没有文件&#xff0c;在vim中保存之后就会有一个文件&#xff0c;相当于记事本里边新建一个文件。我现在就使用vim新建一个文件&#xff0c;然…

C# .NET EF框架 webapi 安装使用sqlite

文章目录 Sqlite安装使用Sqlite特点环境安装EF 是什么&#xff1f;EF使用举例 Nuget控制台 Sqlite安装使用 Sqlite特点 Sqlite是轻量级数据库&#xff0c;不需要安装&#xff0c;跨平台使用。是用来做小软件&#xff0c;小项目&#xff0c;快速移植的最优解。不需要像mysql和…

Verilog基础:表达式中的整数常量(integer)

相关文章 Verilog基础&#xff1a;表达式位宽的确定&#xff08;位宽拓展&#xff09; Verilog基础&#xff1a;表达式符号的确定 Verilog基础&#xff1a;数据类型 Verilog基础&#xff1a;位宽拓展和有符号数运算的联系 Verilog基础&#xff1a;case、casex、ca…

chatgpt赋能python:Python如何Input一个字典:详细教程

Python 如何 Input 一个字典&#xff1a;详细教程 在 Python 中&#xff0c;字典是一种非常有用的数据结构。它可以存储键值对&#xff0c;让我们能够通过键访问值。Python 中没有固定的语法来创建字典&#xff0c;因此本文将教你如何输入一个字典。 什么是字典&#xff1f; …

chatgpt赋能python:Python语言中的Pandas库介绍

Python语言中的Pandas库介绍 Python语言是一种十分流行的编程语言&#xff0c;以其易读易写等特点而受到工程师和数据科学家的青睐。在Python语言中&#xff0c;有一款非常流行的数据处理和分析库&#xff0c;也就是Pandas库。Pandas库在数据处理和分析方面有着出色的表现&…

iOS开发最佳实践|集成声网SDK实现语音聊天室

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c; 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。&#x1f60a; 座右铭&#xff1a;不想当开发的测试&#xff0c;不是一个好…

初探Sharding-JDBC订单表分片实现

设计订单系统有两个数据库db_order_01和db_order_02。每个数据库分别有t_order_0和t_order_1两张订单表。 订单表设计有订单ID(order_id)&#xff0c;用户ID(user_id)&#xff0c;商户ID(merchant_id)。假设商户查看订单操作要比用户查看订单的操作更加频繁。避免商户查询订单时…

NLP学习笔记五-simple RNN

NLP学习笔记五-simple RNN 我这个学习笔记&#xff0c;感兴趣的小伙伴&#xff0c;看的时候尽量从头开始看&#xff0c;这样更好理解&#xff0c;也更有收获。 simple RNN的单元结构图如下&#xff1a; 其中A就是我们需要学习的参数矩阵&#xff0c; h t − 1 h_{t-1} ht−1​…

【MySQL数据库 | 第十五篇】事务

目录 前言&#xff1a; 介绍事务&#xff1a; 控制事务&#xff1a; 事务四大特性&#xff1a; 并发事务问题&#xff1a; 事务隔离级别&#xff1a; 总结: 前言&#xff1a; 这章我们将进入到MySQL基础篇的最后一章&#xff1a;事务&#xff0c;希望大家可以坚持下去&#xf…

车间如何做好“生产计划”,打造高效运营的智能工厂

新形势下&#xff0c;面对外部不断变化的市场需求、供应链下游企业管理升级需求以及持续上涨的人力成本&#xff0c;传统工厂模式必须要变革才能更好地发展。热潮之下&#xff0c;企业纷纷规划建设智能工厂。那么&#xff0c;新工厂规划如何避免投入浪费&#xff0c;少走弯路&a…