编程面试_字符串

news2024/3/4 12:31:26

数据结构

字符串

1 旋转字符串

  给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,
  如把字符串“abcdef”前面的2个字符'a'和'b'移动到字符串的尾部,使得原字符串变成字符串“cdefab”。
  请写一个函数完成此功能,要求对长度为n的字符串操作的时间复杂度为 O(n),空间复杂度为 O(1)。
解法1.1 暴力移位法         将字符一个一个的移动到尾部 或头部
  // 左边的第一个字符移动到最右边
  void LeftShiftOne(char* s, int n)
  {
    char tep = s[0];    // 保存左边的第一个字符 tep
    for (int i = 1; i < n; ++i)
     {
        s[i - 1] = s[i];// 从前向后 靠右的字符 依次向左移动1位
     }
    s[n - 1] = tep;     // tep 放入最右边的位置
  }
  // 右边的第一个字符移动到 最左边
  void RightShiftOne(char* s, int n)
  {
     char tep = s[n - 1];// 保存右边的最后一个字符 tep
     for(int  i = n-1; i > 0; --i)
     {
        s[i] = s[i - 1]; // 从后向前 靠左的字符 依次向右 移动1位
     }
     s[0] = tep;         // tep 放入最左边的位置
  }

因此,若要把字符串开头的m个字符移动到字符串的尾部,则可以如下操作:

void LeftRotateSring(char *s, int n, int m)
{
    while(m--)
    {
         LeftShiftOne(s, n);// 每次移动一个字符 一共 移动 m次
    }
}

而,若要把字符串尾部的m个字符移动到字符串的头部,则可以如下操作:

void ReftRotateSring(char *s, int n, int m)
{
    while(m--)
    {
         ReftShiftOne(s, n);// 每次移动一个字符 一共 移动 m次
    }

}

针对长度为n的字符串来说,假设需要移动m个字符到字符串的尾部,对每个字符需要进行移动n次,那么总共需要 mn 次操作,同时设立一个变量保存第一个字符,如此,时间复杂度为O(m n),空间复杂度为O(1),空间复杂度符合题目要求,但时间复杂度不符合,所以,我们得需要寻找其他更好的办法来降低时间复杂度。

解法1.2:三步反转法
  对于这个问题,换一个角度思考一下。
  将一个字符串XY分成X(m个字符)和Y(n-m个字符)两个部分,在每部分字符串上定义反转操作,
  如X^T,即把X的所有字符反转(如,X="abc",那么X^T="cba"),那么就得到下面的结论:
  (X^TY^T)^T=YX,显然就解决了字符串的反转问题。
  例如,字符串 abcdef ,若要让def翻转到abc的前头,只要按照下述3个步骤操作即可:
  1.首先将原字符串分为两个部分,即X:abc,Y:def;
  2.将X反转,X->X^T,即得:abc->cba;将Y反转,Y->Y^T,即得:def->fed。
  3.反转上述步骤得到的结果字符串X^TY^T,即反转字符串cbafed的两部分(cba和fed)给予反转,cbafed得到defabc,形式化表示为(X^TY^T)^T=YX,这就实现了整个反转。

三个步骤中后两个步骤都用到了 反转一个字符串

  void ReverseString(char *s, int form, int to)
  {
        while(from < to)// 从首尾开始交换首位位置的值,直到相遇
        {
              char tep  = s[from];// 保存左边
              s[from++] = s[to];  //右边 交换给左边 同时左边向右移动一个位置
              s[to--]   = tep;    // 前右边保存的值 交换给左边 同时 右边向左移动一个位置
        }
  }

  // 前 m 后 放在尾部
  // 反转[0..m - 1] 反转[m..n - 1] 反转[0..n - 1]
  void LeftRotateString(char* s, int n, int m)
  {
  m  %= n;// 避免左移数量大于n的情况
  ReverseString(s, 0, m - 1);// 反转[0..m - 1],套用到上面举的例子中,就是X->X^T,即 abc->cba
  ReverseString(s, m, n - 1);// 反转[m..n - 1],例如Y->Y^T,即 def->fed
  ReverseString(s, 0, n - 1);// 反转[0..n - 1],即如整个反转,(X^TY^T)^T=YX,即 cbafed->defabc。
  }
  // 后m个 放在 头部 
  // 反转[0..n - m - 1] 反转[n - m..n - 1] 反转[0..n - 1]
  void LeftRotateString(char* s, int n, int m)
  {
  m  %= n;// 避免左移数量大于n的情况
  ReverseString(s, 0, n - m - 1);// 反转[0..m - 1],套用到上面举的例子中,就是X->X^T,即 abc->cba
  ReverseString(s, n - m, n - 1);// 反转[n - m..n - 1],例如Y->Y^T,即 def->fed
  ReverseString(s, 0, n - 1);// 反转[0..n - 1],即如整个反转,(X^TY^T)^T=YX,即 cbafed->defabc。
  }
1.3 序列反转 举一反三
  1、链表翻转。给出一个链表和一个数k,比如,链表为1→2→3→4→5→6,
  k=2,则翻转后2→1→6→5→4→3,
  若k=3,翻转后3→2→1→6→5→4,
  若k=4,翻转后4→3→2→1→6→5,用程序实现。
  注解:原序列 XY 则反转后的序列为 X^T Y^T

  2、单词翻转。输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变,句子中单词以空格符隔开。
  为简单起见,标点符号和普通字母一样处理。例如,输入“I am a student.”,则输出“student. a am I”。
  注解:先将整个字符串反转,在将其中每个单词反转回来

  void Reverse_word(char *str)      
  {      
      if(str == NULL)// 空指针 返回 
          return;      
      int len = strlen(str);// 字符串长度
      // 反转整个字符串
      ReverseString(str, 0, len - 1);    
      int s = 0;//每个单词的 起始 index
      int e = 0;// 每个单词的 后 index
      for(int i = 0; i < len; i++) // 遍历字符串 查找每一个单词
      {       
          e = i;      
          if(str[e] == ' ')// 此处 遇到空格 
          {      
              ReverseString(str, s, e-1); // 反转这个单词 
              s = e+1;// 更新 单词的起始指针 
          }      
      }    
      ReverseString(str, s, len - 1);  // 反转最后一个单词 因为最后一个单词后面无空格
  }  

2 字符串包含

  给定两个分别由字母组成的字符串A和字符串B,字符串B的长度比字符串A短。请问,如何最快地判断字符串B中所有字母是否都在字符串A里?
  为了简单起见,我们规定输入的字符串只包含大写英文字母,请实现函数bool StringContains(string &A, string &B)
  比如,如果是下面两个字符串:
  String 1:ABCD
  String 2:BAD

答案是true,即String2里的字母在String1里也都有,或者说String2是String1的真子集,当 String 2:BAE 时答案为false

解法2.1 暴力匹配法
  判断string2中的字符是否在string1中?最直观也是最简单的思路是,

针对string2中每一个字符,逐个与string1中每个字符比较,看它是否在String1中。

代码可如下编写:

  bool StringContain(string &a, string &b)
  {
        for(int i = 0; i < b.size(); ++i)
        {
              int j;
              //b中的每一个字符,从a的开头一直向后找,直到出现相同字符/已经到达末尾
              for(j = 0; (j <  a.size()) && (a[j] != b[i]); ++j) ;
              if(j >= a.size()) return false;//如果到达末尾 b中的这个字符 都还没有 在a中找到一样的字符 ,则返回错误
        }
        return true;//b中每个字符都在 a中找到了 返回 true

}

假设n是字符串String1的长度,m是字符串String2的长度,那么此算法,需要O(n*m)次操作。显然,时间开销太大,应该找到一种更好的办法。

解法2.2 排序后匹配法 如果允许排序的话,我们可以考虑下排序
  比如可先对这两个字符串的字母进行排序,然后再同时对两个字串依次轮询。
  两个字串的排序需要(常规情况)O(m log m) + O(n log n)次操作,之后的线性扫描需要O(m+n)次操作。

代码可如下编写:

  //注意A B中可能包含重复字符,所以注意A下标不要轻易移动。这种方法改变了字符串。如不想改变请自己复制
  bool StringContain(string &a,string &b)
  {
      sort(a.begin(),a.end());// 采用最常用的快速排序
      sort(b.begin(),b.end());
      for (int pa = 0, pb = 0; pb < b.length();)// b中的每一个字符
      {
          while ((pa < a.length()) && (a[pa] < b[pb]))// 在a中找 
          {
              ++pa;
          }
          if ((pa >= a.length()) || (a[pa] > b[pb]))//找到最后 或 a中的字符已经大于b对应的字符了 就已经无相等的了
          {
              return false;
          }
          //到这里就是 有相同的字符 a[pa] == b[pb]
          ++pb;//遍历 b中 下一个字符
      }
      return true;
  }
解法2.3 素数乘积取余法
  按照从小到大的顺序,用26个素数分别与字符'A'到'Z'一一对应。

遍历长字符串,求得每个字符对应素数的乘积f。
     遍历短字符串,判断乘积f 能否被短字符串中的字符对应的素数整除,如果整除则包含该字符,如果不能整除则这个字符不包含。
输出结果。

代码可如下编写:

  //此方法只有理论意义,因为整数乘积很大,有溢出风险
  // 此种素数相乘的方法看似完美,但缺点是素数相乘的结果容易导致整数溢出。
  // 算法的时间复杂度为O(m+n)的最好的情况为O(n)
  //(遍历短的字符串的第一个数,与长字符串素数的乘积相除,即出现余数,便退出,返回false)n为长字串的长度,空间复杂度为O(1)
  bool StringContain(string &a,string &b)
  {
      const int p[26] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,61, 67, 71, 73, 79, 83, 89, 97, 101};
      int f = 1;
      for (int i = 0; i < a.length(); ++i)
      {
          int x = p[a[i] - 'A'];// 字符对应的素数
          if (f % x)// 对于长字符串中出现相同的字符 可不用再次 相乘
          {
              f *= x;// a中所有不相同字符 对应的素数 的乘积
         }
      }
      for (int i = 0; i < b.length(); ++i)
      {
          int x = p[b[i] - 'A'];// 字符对应的素数
          if (f % x)// 能够被整除 则说明出现相同的字符
          {
              return false;// 否者出现 了一个不相同的字符 则退出
          }
      }
      return true;
  }
解法2.4 Hash 签名查找
  事实上,可以先把长字符串a中的所有字符都放入一个Hashtable里,
  然后轮询短字符串b,看短字符串b的每个字符是否都在Hashtable里,
  如果都存在,说明长字符串a包含短字符串b,否则,说明不包含。
  再进一步,我们可以对字符串A,用位运算(26bit整数表示)计算出一个“签名”,再用B中的字符到A里面进行查找。

代码可如下编写:

  // “最好的方法”,时间复杂度O(n + m),空间复杂度O(1)
  // 这个方法的实质是用一个整数代替了hashtable,空间复杂度为O(1),时间复杂度还是O(n + m)。
  bool StringContain(string &a,string &b)
  {
      int hash = 0;
      for (int i = 0; i < a.length(); ++i)
      {
          hash |= (1 << (a[i] - 'A'));// (a[i] - 'A')为0~25 右移动一位 位或上签名hash 得到 长串a的最后签名
          // 相当于把 a的每一个不同的 字符 放入 每一个而进行位上
      }
      for (int i = 0; i < b.length(); ++i)
      {
          if ((hash & (1 << (b[i] - 'A'))) == 0)// 位与 上(1 << (b[i] - 'A')) 的0的话就说明对应的位上(字符)与a中午匹配
          {
              return false;// 对应位上 a中未出现相应的字符  则查找失败
          }
      }
      return true;
  }
2.5 字符串包含 举一反三 变位词
  如果两个字符串的字符一样,但是顺序不一样,被认为是兄弟字符串。
  比如bad和adb即为兄弟字符串,现提供一个字符串,如何在字典中迅速找到它的兄弟字符串,请描述数据结构和查询过程。

解答: a包含b b也包含a
     数据结构为:
设置一个64bit的变量long long hash1,将字符串A中的字符通过移位在hash1中表示;设置另外一个64bit的变量long long hash2, 将字符串B中的字符通过移位在hash2中表示。
查询过程:
比较hash1与hash2的大小,若相等,则为兄弟字符串;若不等,则不为兄弟字符串。

代码可如下编写:

  bool anagramJudge(string &a, string &b){
      long long hash1=0;
      long long hash2=0;
      for(int i=0; i<a.length(); i++){
          hash1 |= (1<<(a[i] - 'A'));// a字符串的 hash 签名
      }
      for(int j=0; j<b.length(); j++){
          hash2 |= (1<<(b[j] - 'A'));// b字符串的 hash 签名
      }
      if(hash1 == hash2)// 若相等,则为兄弟字符串
          return true;
      else
          return false;// 若不等,则不为兄弟字符串
  }

3字符串转换成整数

  输入一个由数字组成的字符串,把它转换成整数并输出。
  例如:输入字符串"123",输出整数123。
  给定函数原型int StrToInt(const char *str) ,
  实现字符串转换成整数的功能,不能使用库函数atoi。
3.1不考虑溢出 正负号
  以"123"作为例子:
     当我们扫描到字符串的第一个字符'1'时,由于我们知道这是第一位,所以得到数字1。
     当扫描到第二个数字'2'时,而之前我们知道前面有一个1,
  所以便在后面加上一个数字2,那前面的1相当于10,因此得到数字:1*10+2=12。
     继续扫描到字符'3','3'的前面已经有了12,由于前面的12相当于120,
  加上后面扫描到的3,最终得到的数是:12*10+3=123。
  因此,此题的基本思路便是:
  从左至右扫描字符串,把之前得到的数字乘以10,再加上当前字符表示的数字。

代码可如下编写:

  int StrToInt(const char *str)
  {
      if(str == NULL)   // 空指针返回
         return -1;
      int n = 0;
      int isNeg = 0;    // 负数标志
      if(str[0] == '-') isNeg = 1;
      while (*str != 0) // 遍历到字符串末尾
      {
          if(*str > '9' || *str < '0') {continue; ++str;}// 跳过非数字字符 或者 直接 退出 return -1;
          int c = *str - '0';
          n = n * 10 + c;// 累加和
          ++str;         // 移动指针
      }
      if(isNeg) return -n;
      else      return n;
  }
3.2 完整的考虑溢出等情况
  int StrToInt(const char* str)
  {
      static const int MAX_INT = (int)((unsigned)~0 >> 1);
      static const int MIN_INT = -(int)((unsigned)~0 >> 1) - 1;
      unsigned int n = 0;

      //判断是否输入为空
      if (str == 0)
      {
          return 0;
      }

      //处理空格 跳过第一个空格
      while (isspace(*str))
          ++str;

      //处理正负
      int sign = 1;
      if (*str == '+' || *str == '-')
      {
          if (*str == '-')
              sign = -1;
          ++str;// 如果有正负号 确定标志后 从符号后一位开始处理
      }

      //确定是数字后才执行循环
      while ( *str > '0' && *str < '9' )
      {
          //处理溢出
          int c = *str - '0';// 字符转换成 数字
          if (sign > 0 && (n > MAX_INT / 10 || (n == MAX_INT / 10 && c > MAX_INT % 10)))
          {
              n = MAX_INT;
              break;
          }
          else if (sign < 0 && (n >(unsigned)MIN_INT / 10 || (n == (unsigned)MIN_INT / 10 && c > (unsigned)MIN_INT % 10)))
          {
              n = MIN_INT;
              break;
          }

          //把之前得到的数字乘以10,再加上当前字符表示的数字。
          n = n * 10 + c;
          ++str;
      }
      return sign > 0 ? n : -n;
  }
3.3 举一反三
  实现string到double的转换

代码可如下编写:

  double StrToDou(const char *str)
  {
      if(str == NULL)   // 空指针返回
         return -1;
      double result = 0.0;// 最后的值
      double dec = 10.0;// 小数位比值
      int isNeg = 0;   // 负数标志
      int isDec = 0;
      if(str[0] == '-') isNeg = 1;
      while (*str != 0) // 遍历到字符串末尾
      {
          if(*str == '.') {isDec = 1; ++str;}//是小数
          else if(*str > '9' || *str < '0') {continue; ++str;}// 跳过非数字字符 或者 直接 退出 return -1;
          if(!isDec) // 整数部分
              result = result * 10 + *str - '0';// 整数部分 累加和
          else //识别小数点之后进入 这个分支
              { 
               result = result + (*str - '0')/dec;// 小数部分 算法
               dec *= 10;// 小数位比值递增
              }
          ++str;         // 移动指针
      }
      if(isNeg) return -result;
      else      return result;
  }

4 字符串 回文 判断

4.1 首尾并进判断法
  同时从字符串头尾开始向中间扫描字串,如果所有相对的字符都一样,那么这个字串就是一个回文。
  采用这种方法的话,我们只需要维护头部和尾部两个扫描指针即可。 Palindrome  英 ['pælɪndrəʊm]  pai lin drow mu

代码可如下编写:

  // 输入字符指针 s 和 字符串大小 num
  bool IsPalindrome(const char* s, int num)
  {
        if(s == NULL || num < 2)  return false;//指针为空 / 字符串长度小于2
        // 定义并初始化 首尾指针
        const char* low, *high;// 首尾指针
        low = s;// 首指针
        high = s + num - 1;// 尾指针
        while(low < high){
              if(*low ! *high) return false;// 出现一次相对应位置的字符不相同 就返回错误
              ++low;
              --high;
        }
        return true; // 到这里的话 就证明 相对应位置上的 字符相同 为 回文
  }

这是一个直白且效率不错的实现,时间复杂度:O(n),空间复杂度:O(1)。
上述解法一从两头向中间扫描,那么是否还有其它办法呢?我们可以先从中间开始、然后向两边扩展查看字符是否相等。

判断一条单向链表是不是“回文
  对于单链表结构,可以用两个指针从两端或者中间遍历并判断对应字符是否相等。
  但这里的关键就是如何朝两个方向遍历。由于单链表是单向的,所以要向两个方向遍历的话,可以采取经典的快慢指针的方法,
  即先位到链表的中间位置,再将链表的后半逆置,最后用两个指针同时从链表头部和中间开始同时遍历并比较即可。
判断一个栈是不是“回文”
  对于栈的话,
  只需要将字符串全部压入栈,然后依次将各字符出栈,
  这样得到的就是原字符串的逆置串,

将逆置串和原字符串各个字符比较,就可以判断了。

5 最长回文子串

如果一段字符串是回文,那么以某个字符为中心的前缀和后缀都是相同的,
例如以一段回文串“aba”为例,以b为中心,它的前缀和后缀都是相同的,都是a。
     那么,我们是否可以可以枚举中心位置,然后再在该位置上用扩展法,记录并更新得到的最长的回文长度呢?

5.1 遍历子串中心位置,找最大回文子串(分为子串长度为 奇数和偶数的情况)

参考代码如下:

  int LongestPalindrom(const char* s, int num){
  if(s == NULL || num < 2)  return false;//指针为空 / 字符串长度小于2
  int i,j,max,cnt;// ij 为循环变量 cnt 记录每一个回文子串的长度
  max = 0;//最大字回文字符串长度 初始化为0

  // 遍历每一个子串 的 中心点
  for(i = 0; i < n; ++i){ 
     // 对于子串长度为奇数的情况
       for(j = 0; (i - j >= 0)&&(i + j < n); ++j){// j为以i字符点为中心 向两边扩展的间隔 区别首尾区间 [0, n-1]
              if(s[i - j] != s[i + j]) break; // 间隔相同的位置 字符不同 结束回文
              cnt = j*2 + 1;// 已此中心点i 的回文子串长度为 间隔j *2 + 1(中间一个字符)
        }
        if(cnt > max) max = cnt;// 保存最长的 回文子串的 长度

    // 对于子串 长度为 偶数的情况
        for(j = 0; (i - j >= 0)&&(i + j + 1 < n); ++j){
              if(s[i - j] != s[i + j +1]) break; // 间隔相同的位置 字符不同 结束回文
              cnt = j*2 + 2;
        }
        if(cnt > max) max = cnt;// 保存最长的 回文子串的 长度   
   }
  return max;
  }

6 字符串的全排列

  输入一个字符串,打印出该字符串中字符的所有排列。
  例如输入字符串abc,则输出由字符a、b、c 所能排列出来的所有字符串
  abc、acb、bac、bca、cab 和 cba。
6.1 递归实现
  从集合中依次选出每一个元素,作为排列的第一个元素,然后对剩余的元素进行全排列,
  如此递归处理,从而得到所有元素的全排列。     Permutation  英 [pɜːmjʊ'teɪʃ(ə)n]  Peer mu tai xing
  以对字符串abc进行全排列为例,我们可以这么做:以abc为例 

abc a和a交换后 abc 对a后的 bc进行全排列
     abc a和b交换后 bac 对b后的 ac进行全排列
     abc a和c交换后 cba 对c后的 ba进行全排列

参考代码如下:

  void CalcAllPermutation(char* s, int from, int to)
  {
  if (s == NULL || to < 2)  return;

  // 打印排列后的字符串
  if (from == to)/
  {
    for (int i = 0; i <= to; i++)
        cout << perm[i];
    cout << endl;
  }
  else
  {
    for (int j = from; j <= to; j++)// 从当前位置from开始 依次向后和j位置交换元素后 对from后的元素进行全排列
    {
        swap(perm[j], perm[from]);// 从当前位置from开始 依次向后和j位置交换元素
        CalcAllPermutation(perm, from + 1, to);// 对from后的元素 [from + 1, to]进行全排列
        swap(perm[j], perm[from]);// 再还原字符串
    }
  }
  }

习题集

1 第一个只出现一次的字符

  在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。

遍历法

  //O(n^2)的时间复杂度
  char FirstNotRepeatingChar(char *pS, int num)
  {
      //如果是空指针,返回\0
      if(pS == NULL) return '\0';
      int i,j,flag=0;
      bool* bap;
      bap = (bool*)maoolc(sizeof(bool)*num);
      for(i =0; i < n; ++i) *bap[i] = false;
      for(i=0; i<num-1; ++i)// 遍历 前置 字符
      { 
          if(*bap[i]) continue;// 当前 字符串 之前出现过 跳过本次循环   有问题 后面再出现相同的呢???
          for(j=i+1; j<len; ++j)// 和其后面的字符 依次作比较
          {
              if(pS[i] == pS[j]) {*bap[j] = true; break;}// i位置上的字符 后面有出现 跳过 这个字符
          }
          return pS[i];// 打印这个出现一次的字符
      }
      return '\0';
  }

哈希表法 强烈推荐

  //O(n)的时间复杂度
  char FirstNotRepeatingChar(char *pS)
  {
      //如果是空指针,返回\0
      if(pS == NULL)  return '\0';
      //字符(char)是一个长度为8bit的数据类型,因此总共最多能够表示256种字符。 
      //定义hash表长度256,并创建哈希表
      const int len=256;
      int hashtable[len];
      for(int i=0;i<len;i++)  hashtable[i]=0;

      char *pHashkey=pS;
      // 第一遍遍历字符串,求出每个字符出现的次数
      // 字符根据其ASCII值作为数组的下标对应数组的一个数字,而数组中存储的是每个字符出现的次数
      while((*pHashkey)!='\0') hashtable[*(pHashkey++)]++;
      pHashkey=pS;
      //第二遍遍历字符串,求出第一个只出现一次的字符,每次都是按照字符串的顺序遍历
      while((*pHashkey)!='\0')
      {
          if(hashtable[*pHashkey]==1)// 记录只出现一次
              return *pHashkey;
          pHashkey++;
      }
      return '\0';
  }

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

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

相关文章

《C++ Primer》练习7.31:定义互相嵌套的类

类可以先声明再定义&#xff0c;可以用下面这个题目理解一下 class Y; class X {Y *y; };class Y {X x; };未出现的类类型要在前面声明。 参考 《C Primer》

前端架构师之02_ES6_高级

1 类和继承 1.1 class类 JavaScript 语言中&#xff0c;生成实例对象的传统方法是通过构造函数。 // ES5 创建对象 // 创建一个类&#xff0c;用户名 密码 function User(name,pass){// 添加属性this.name name;this.pass pass; } // 用 原型 添加方法 User.prototype.sho…

集合-ArrayList源码分析(面试)

系列文章目录 1.集合-Collection-CSDN博客​​​​​​ 2.集合-List集合-CSDN博客 3.集合-ArrayList源码分析(面试)_喜欢吃animal milk的博客-CSDN博客 目录 系列文章目录 前言 一 . 什么是ArrayList? 二 . ArrayList集合底层原理 总结 前言 大家好,今天给大家讲一下Arra…

使用Qt验证RGB格式

下面我们用不同的颜色来绘制一块矩形区域&#xff0c;来对比学习RGB颜色。 一片漆黑的黑色 黑色在RGB中是三个颜色分量都是0。也就是没有颜色。 下面我们绘制一个水平100个像素&#xff0c;垂直200个像素的矩形区域&#xff0c;颜色设置为黑色。 #ifndef MAINWINDOW_H #def…

基于B2B平台的医疗病历交互系统

目录 前言 一、技术栈 二、系统功能介绍 医院管理 医院注册 医院文章 医生信息 医院注册 医疗安排 院区注册 医院公告 医院工作人员 病人病历 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 进入21世纪&#xff0c;计算机技术迅速向着网络化的、集…

el-menu 导航栏学习(1)

最简单的导航栏学习跳转实例效果&#xff1a; &#xff08;1&#xff09;index.js路由配置&#xff1a; import Vue from vue import Router from vue-router import NavMenuDemo from /components/NavMenuDemo import test1 from /components/test1 import test2 from /c…

Qt::图层框架-图片图层-序列图层-QGraphicsPixmapItem

二维矢量动画智能制作软件开发合集 链接&#xff1a;软件开发技术分享及记录合集 个人开发二维矢量动画智能制作软件界面如下&#xff1a; 目录 一、图片序列图层原理 二、图片序列图层代码实现 三、图片序列图层软件测试视频 结束语 一、图片序列图层原理 本软件的11种…

凉鞋的 Godot 笔记 102. 场景与节点的增删改查

在上一篇&#xff0c;我们完成了 Godot 引擎的 Hello World 输出&#xff0c;并且完成了第一个基本循环: 通过这次基本循环的完成&#xff0c;我们获得了一点点的 Godot 使用经验&#xff0c;这非常重要。 有实践经验后再去补充理论 和 先学习理论后去实践相比&#xff0c;前者…

面试总结之Spring篇

一、AOP 1、什么是AOP 1.1、概述 AOP&#xff08;Aspect-Oriented Programming&#xff09;&#xff1a;面向切面编程&#xff0c;即把一些业务逻辑中的相同代码抽取出来&#xff0c;让业务逻辑更加简练清爽 如果要CRUD写一堆业务&#xff0c;可如何实现业务代码前后进行打印…

2023年中国智能电视柜产量、需求量、市场规模及行业价格走势[图]

电视柜是随着电视机的发展和普及而演变出的家具种类&#xff0c;其主要作用是承载电视机&#xff0c;又称视听柜&#xff0c;随着生活水平的提高&#xff0c;与电视机相配套的电器设备也成为电视柜的收纳对象。 随着智能家具的发展&#xff0c;智能电视机柜的造型和风格都是有了…

前端最新支持四级及以下结构仿企查查、天眼查关联投资机构 股权结构 tree树形结构 控股结构

随着技术的发展&#xff0c;开发的复杂度也越来越高&#xff0c;传统开发方式将一个系统做成了整块应用&#xff0c;经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改&#xff0c;造成牵一发而动全身。通过组件化开发&#xff0c;可以有效实现单…

【大规模 MIMO 检测】基于ADMM的大型MU-MIMO无穷大范数检测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Cannot download sources:IDEA源码无法下载

问题 Swagger的相关包&#xff0c;无法看到注释&#xff1b; 在class文件的页面&#xff0c;点击下载源码&#xff0c;源码下载不了&#xff0c;IDEA报下面的错误。 报错 Cannot download sources Sources not found for: io.swagger.core.v3:swagger-annotations:2.2.9 解决…

二值贝叶斯滤波计算4d毫米波聚类目标动静属性

机器人学中有些问题是二值问题&#xff0c;对于这种二值问题的概率评估问题可以用二值贝叶斯滤波器binary Bayes filter来解决的。比如机器人前方有一个门&#xff0c;机器人想判断这个门是开是关。这个二值状态是固定的&#xff0c;并不会随着测量数据变量的改变而改变。就像门…

Android Jetpack组件架构:ViewModel的原理

Android Jetpack组件架构&#xff1a;ViewModel的原理 导言 本篇文章是关于介绍ViewModel的&#xff0c;由于ViewModel的使用还是挺简单的&#xff0c;这里就不再介绍其的基本应用&#xff0c;我们主要来分析ViewModel的原理。 ViewModel的生命周期 众所周知&#xff0c;一般…

FFmpeg 命令:从入门到精通 | ffplay 简单过滤器

FFmpeg 命令&#xff1a;从入门到精通 | ffplay 简单过滤器 FFmpeg 命令&#xff1a;从入门到精通 | ffplay 简单过滤器视频旋转视频反转视频旋转和反转音频变速播放视频变速播放音视频同时变速更多参考 FFmpeg 命令&#xff1a;从入门到精通 | ffplay 简单过滤器 本节介绍了简…

亲测可用国产GPT人工智能

分享一些靠谱、可用、可以白嫖的GPT大模型。配合大模型&#xff0c;工作效率都会极大提升。 清华大学ChatGLM 官网&#xff1a; 智谱清言中国版对话语言模型&#xff0c;与GLM大模型进行对话。https://chatglm.cn/开源的、支持中英双语的1300亿参数的对话语言模型&#xff0…

毅速课堂:3D打印随形水路设计应注意什么?

随形水路是一种基于3D打印技术的新型模具冷却水路&#xff0c;能有效提高冷却效率、缩短冷却周期、提升产品良率、提高生产效率、 与传统的水路设计相比&#xff0c;随形水路更加贴合模具型腔表面&#xff0c;能够更加均匀地分配冷却水&#xff0c;使模具各部分的冷却效果得到有…

Android 使用Kotlin封装RecyclerView

文章目录 1.概述2.运行效果图3.代码实现3.1 扩展RecyclerView 3.2 扩展Adapter3.3 RecyclerView装饰绘制3.3.1 以图片实现分割线3.3.2 画网格线3.3.3空白的分割线3.3.4 不同方向上的分割线 3.4 使用方法 1.概述 在一个开源项目上看到了一个Android Kotlin版的RecyclerView封装…

Egg 封装接口返回信息

中间件封装 代码 const msgArr {"200":成功,"401":token失效 } module.exports (option, app) > {return async function(ctx, next) {try{//成功是返回的信息ctx.emit(code,data,msg)>{console.log(1111,code,data,msg)ctx.body {code,data:dat…