中等题 ------ 数组以及字符串

以前刷的都是一些简单题,从一些基本的数据结构到算法,得有400多道了,简单题就先这样吧,从今天以后就开始着手中等题和困难题了。
做了一些中等题,感觉确实和简单题没法比,简单题有些直接模拟,暴力就能做出来,而这些中等题是根本想不到该怎么做,但看了题解,找到公式关系,规律也就觉得还行,慢慢加油吧。
本篇是一些关于数组和字符串的题。
数组和字符串的简单题在这。

文章目录

  • 1. 数组嵌套
  • 2. 非递减数列
  • 3. 最佳观光组合
  • 4. 对角线遍历
  • 5. 生命游戏
  • 5. 分割数组
  • 6. 找出数组游戏的赢家
  • 7.除自身以外数组的乘积
  • 8. 旋转函数
  • 9. 旋转图像
  • 10.递增三元子序列
    • (1)两次遍历
    • (2)贪心
  • 11. 优美的排列
  • 12.盛最多水的容器
  • 13. 三数之和
  • 14.下一个排列
  • 15. Z 字形变换
  • 16. 验证IP地址????(可以不看,本人的痛苦回忆)
  • 17. 破坏回文串
  • 18. 竖直打印单词
  • 19.在LR字符串中交换相邻字符
  • 20. 情感丰富的文字
  • 21.字符串转换整数(atoi)
  • 22. HTML实体解析器
  • 23.无重复的字串
  • 24. 最长回文子串
    • (1)暴力美学(YYDS!!)
    • (2)动态规划
    • (3)双指针(中心扩散)
  • 25.整数转罗马数字
  • 26. 电话号码的字母组合
  • 27.外观数列
  • 28.编辑距离
  • 29.解码方法
  • 30. 交错字符串

1. 数组嵌套

在这里插入图片描述
这道题的意思就是说你嵌套的去访问,直接模拟题目的意思,看看那一个的长度最长就好了。
测试用例所给的S[0],模拟出其他的S[1~6]这都是可以模拟出来的,但是会超出时间限制。
需要一些技巧,将其转化成图的形式更直观一点,你会发现这个图是,一个带多个环的图,选出其中环顶点的那一个就好了,而遍历图的精髓则在于那一个Vist数组标记着当前顶点是否访问过。
在这里插入图片描述

  • 创建一个visit数组来标识该顶点是否访问过。
  • 然后在遍历数组,如果没访问过,循环与他有关的顶点,同时将其相关的顶点也加入到Vist数组中去。
int Max(int x, int y)
{return x > y ? x  : y;
}int arrayNesting(int* nums, int numsSize)
{int i,maxLen = 1;int* visit = (int*)calloc(numsSize,sizeof(int));for (i = 0; i < numsSize; i++){//访问过直接返回就好了if(visit[i] == 1){continue;}visit[i] = 1;int j = nums[i], len = 1;//未访问过的while(visit[j] != 1){len++;visit[j] = 1;j = nums[j];}maxLen = Max(maxLen,len);}return maxLen;
}

2. 非递减数列

在这里插入图片描述
这道题的意思就是说,你可以修改数组中的一个数,但要保证修改完后,可以是非递减的数列,比如这两者种序列: 1 2 3 4 和1 1 2 3都属于非递减数列。

看下图种,要想一个数列是递增的,i所指向的数如果大于下一个数,就说明称递减了。
所以我们就要对其进行修改,下面是三种情况,其实仔细看看会发现,第一种情况它可以将4修改为1或者是2都没有关系,而官方给的是修改成1,让他变成1 2 3这一个数列。
又因为他是要改变为非递增的,所以说分为右边的两种情况:

 - nums[i - 1] <= nums[i + 1] 使nums[i] = nums[ i + 1]- nums[i - 1] >  nums[i + 1] 使nums[i + 1] = nunm[i]

在这里插入图片描述

 - 而对于边界0下标来说,不管将自己改成哪一种?都不会影响最后的结果。

在这里插入图片描述
而将i的位置就该后,如果还出现递减的情况,就说明修改一次不行,返回false就好了

bool checkPossibility(int* nums, int numsSize)
{int i,count = 0;for (i = 0; i < numsSize - 1; i++){//发现递减时候if(nums[i] > nums[i + 1]){count++;if(i > 0 && nums[i - 1] > nums[i + 1]){nums[i + 1] = nums[i];}else{nums[i] = nums[i + 1];}}}return count < 2;
}

3. 最佳观光组合

在这里插入图片描述
这道题就题目中已经给出公式,要求出values[i] + values[j] + i - j 的最大值。
使用暴力双for肯定是会超时的,所以得进行优化。
下面是leetcode官方的题解,转换式子拿一下确实妙啊。

 -  values[i] + values[j] + i - j 可以变成 values[i] + i + valuse[j] - j 的形式- 我们可以直接拿一个变量 max 来存储 values[i] + i 的值,- 这样就变成了一个max +  valuse[j] - j 的形式(妙。。)- 这样子的话,i全部在一起,j全部在一起,就可以通过遍历一遍来实现。

注意一定是先去求答案,再去维护最大值,就会算出自己+自己情况,那样子是错的。

int maxScoreSightseeingPair(int* values, int valuesSize)
{   int i = 0,j,max = values[0],ans = max;for (j = 1; j < valuesSize;j++){//先去求ansif(max + values[j] - j > ans){ans = max + values[j] - j;}//再去维护最大值if(values[j] + j > max){max = values[j] + j;}}    return ans;
}

4. 对角线遍历

在这里插入图片描述

这道题的意思就是让你看图片,懂了吗?不行再看下一张,ok了不?
在这里插入图片描述

 - 首先先看普通情况,就是说如果右上走的话:x--,y++.左下走的话使x++,y--;- 但是要注意边界条件,上下左右四个边界条件。- 上下:如果x == 0  || x == row - 1了,再动就出界了,只需要将y++即可。- 左右:如果y == 0 || y == col - 1,那么肯定是x++;

移动能移动了,还需要判断它往那个方向移动。

 - (x + y) % 2 偶数向右上移动,奇数向左下移动。
/*** Note: The returned array must be malloced, assume caller calls free().*/
int* findDiagonalOrder(int** mat, int matSize, int* matColSize, int* returnSize)
{int size = matSize * matColSize[0];int* ans = (int*)malloc(sizeof(int) * size);*returnSize = size;int index = 0;int row = matSize, col = matColSize[0];int x = 0, y = 0;while(index < size){ans[index++] = mat[x][y];if ((x + y) % 2 == 0){//右上方去遍历if(y < col - 1){y++;if(x > 0){x--;}}else{x++;}}else{//往左下方去遍历if(x < row - 1){x++;if(y > 0){y--;}}else{y++;}}}return ans;
}

5. 生命游戏

在这里插入图片描述
这道题的意思是统计出自身周围8个位置(以自身为坐标9宫格)有多个活着的细胞也就是1,判断那四种生存定律就好了。

int GetLive(int** board, int row, int col, int x, int y)
{int coordX[8] = {-1,-1,-1,0,1,1,1,0};int coordY[8] = {-1,0,1,1,1,0,-1,-1};int i,count = 0;for (i = 0; i < 8; i++){int dx = coordX[i] + x;int dy = coordY[i] + y;//范围合理if(dx >= 0 && dx < row && dy >= 0 && dy < col){if(board[dx][dy] == 1){count++;}}}return count;
}void gameOfLife(int** board, int boardSize, int* boardColSize)
{int row = boardSize, col = boardColSize[0];int** tmpBoard = (int**)malloc(sizeof(int*) * row);int i,j;for (i = 0; i < row; i++){tmpBoard[i] = (int*)malloc(sizeof(int) * col);for (j = 0; j <  col; j++){tmpBoard[i][j] = board[i][j];}}for (i = 0; i < row; i++){for (j = 0; j < col; j++){//求出周围或者的细胞有多少个int live = GetLive(tmpBoard,row,col,i,j);if(board[i][j] == 1 && (live < 2 || live > 3)){board[i][j] = 0;}else if(board[i][j] == 0 && live == 3){board[i][j] = 1;}}}
}

5. 分割数组

在这里插入图片描述
这道题是说将数组分成两部分,左边的数必须全部都小于或者等于右边的数。

 - 那么我们可以发现,只要说左边最大的那个数,小于右边最小的那个数就好了。- 上面这句话都能想到,但是针对于左边和右边这俩区间又该如何选择,这是难点。
  • 从右往左,拿一个minRight数组记录着右边出现的最小值,就比如下面这张图,计算出每个区间的最值。
    在这里插入图片描述
  • 有了每个区间的最小值后,再从左边往右遍历,拿一个maxLeft记录当前所走过的最大值,如果发现最大值小于右边的最小值,return 就好了,
  • 不能是maxLeft 小于等于 right[i + 1] 因为他要求长度最短,所以 不能等于.
  • 还有一种情况就是,如果遍历到numsSize - 1的位置,题目中的测试用例都是合法的。所以只能分成left = [0,numsSize - 1]
    在这里插入图片描述
    下面是代码:
int partitionDisjoint(int* nums, int numsSize)
{int* minRight = (int*)malloc(sizeof(int) * numsSize);int i;minRight[numsSize - 1] = nums[numsSize - 1];//求出右边数组的最小值for (i = numsSize - 2; i >= 0; i--){minRight[i] = Min(nums[i],minRight[i + 1]);}int maxLeft = nums[0];  for (i = 0; i < numsSize - 1; i++){//左边记录最大的if(nums[i] > maxLeft){maxLeft = nums[i];}if(maxLeft <= minRight[i + 1]){   //发现左最大数小于了右边最小的数停下来就行了return i + 1;}}return numsSize - 1;
}

6. 找出数组游戏的赢家

在这里插入图片描述
这道题的意思就是就是拿第一个数据和下一个去比较。大的放在第一位,小的去最后一位。

 - 第一种情况下:arr[1] < arr[0] 发现可以少去挪动数据的过程直接让i++也是一样的道理- 同样是指向下一个3.- 而max还是nums[0]不需要去移动,win++;

在这里插入图片描述

 -  而如果max 小于了arr[i]时候,更新一下新的max值,和图三意思是一样的。-  要注意的是,不管之前的win是多少,一定得修改成1,因为这是他第一次赢。-  中途如果win == k了返回当前的max就好了

在这里插入图片描述

 - 如果经过这一轮的遍历都没有能达到k次的数。返回最大值就好了。
int Max(int x, int y)
{return x > y ? x : y;
}int getWinner(int* arr, int arrSize, int k)
{int i = 1,max = arr[0],win = 0;for (i = 1; i < arrSize; i++){if(max > arr[i]){win++;}else{max = arr[i];win = 1;}if(win == k){return max;}}return max;
}

7.除自身以外数组的乘积

在这里插入图片描述
这道题的意思是给一个数组,对不ans[i] = 除了nums[i] 之外的全部元素的乘积。
首先使用暴力双for会超时,还不让用除法。

 - 看下图,我们可以知道对于nums[i]等于它的前缀积 * 后缀积- 而首位两项直接采用就好了。

在这里插入图片描述
下面是代码:

int* productExceptSelf(int* nums, int numsSize, int* returnSize)
{int* ans = (int*)malloc(sizeof(int) * numsSize);*returnSize = numsSize;int* prefix = (int*)malloc(sizeof(int) * numsSize);int* suffix = (int*)malloc(sizeof(int) * numsSize);int i,tmp = 1;//前缀积for (i = 0; i < numsSize; i++){prefix[i] = (tmp *= nums[i]);}//后缀积tmp = 1;for (i = numsSize - 1; i >= 0; i--){suffix[i] = (tmp *= nums[i]);}//首位两项直接赋值ans[0] = suffix[1];ans[numsSize - 1] = prefix[numsSize - 2];//num[i] = 前缀 * 后缀for (i = 1; i < numsSize - 1; i++){ans[i] = prefix[i - 1] * suffix[i + 1];}return ans;
}

8. 旋转函数

在这里插入图片描述
这道题应算肯定是能算,但是一定会超时,需要推导出一个公式来。

 - f[0]: 0 nums[0] + 1*nums[1] + 2*nums[2] + 3*nums[3]- f[1]: 1*nums[0] + 2*nums[1] + 3*nums[2] + 0*nums[3]- f[2]: 2*nums[0] + 3*nums[1] + 0*nums[2] + 1*nums[3]- f[1] - f[0] = nums[0] + nums[1] + nums[2] + nums[3] - 4*nums[3]- 		  f[1] = f[0] + numSum - 4 * nums[4 - 1];- f[2] - f[1] = nums[0] + nums[1] + nums[2] + nums[3] - 4*nums[2]- 		  f[2] = f[1] + numSum - 4 * nums[4 - 2];-所以 f[n] = f[n-1] + numSum - numsSize * nums[numSize - n];
int maxRotateFunction(int* nums, int numsSize)
{int f = 0, sum = 0;// f为旋转函数的值,sum为数组全部数据之和int i;//先求出f[0]的值,即可求出f[1].......f[n-1]的值for (i = 0; i < numsSize; i++){f += i * nums[i];sum += nums[i];}int ans = f;for (i = 1; i < numsSize; i++){//公式f = f + sum - numsSize * nums[numsSize - i];ans = Max(ans,f);}return ans;
}

9. 旋转图像

在这里插入图片描述
这道题的的意思是,将第一行变成最后一列,第二行变成倒数第二列…
如果创建一个辅助矩阵,直接赋值是可以的,但是题目中的意思是原地修改。

 - 我们可以先将矩阵按照副对角线反转矩阵。- 然后将每一列进行逆序就可以了。
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}void rotate(int** matrix, int matrixSize, int* matrixColSize)
{int n = matrixSize;int i,j;//先沿着副对角线反转for (i = 0; i < n - 1; i++){for (j = 0; j < n - i - 1; j++){Swap(&matrix[i][j],&matrix[n - j - 1][n - i - 1]);            }}//将矩阵每一列进行逆序。for (i = 0; i < n; i++){int top = 0, low = n - 1;while(top < low){Swap(&matrix[top++][i],&matrix[low--][i]);}}}

10.递增三元子序列

在这里插入图片描述
这道题是要求我们在数组中找到三个下标i j k 使其呈递增数列,i j k 下标可以不连续,但是必须满足 i < j < k的形式

(1)两次遍历

 - 要想递增,那么左边的数也就是 i下标 那个数一定得是最小的。- 相反右边 k 下标所对应的数一定是大,- 所以我们可以通过两次遍历,分别对数组求出左边的最小值,和右边的最大值。- 然后如果有一个下标 j 满足 minLef < nums[j] < maxRight, 就好了

在这里插入图片描述

bool increasingTriplet(int* nums, int numsSize)
{int* minLeft= (int*)malloc(sizeof(int) * numsSize);int* maxRight = (int*)malloc(sizeof(int) * numsSize);int i;//分别求出左边最小值和右边的最大值minLeft[0] = nums[0];for (i = 1; i < numsSize; i++){minLeft[i] = Min(minLeft[i-1],nums[i]);}maxRight[numsSize - 1] = nums[numsSize - 1];for (i = numsSize - 2; i >= 0; i--){maxRight[i] = Max(maxRight[i + 1],nums[i]);}for (i = 1; i < numsSize - 1; i++){if(nums[i] > minLeft[i-1] && nums[i] < maxRight[i+1]){return true;}}return false;
}

(2)贪心

 - 需要我们在遍历数组的时候,用两个变量,维护者第一个数和第二个。- 如果当前的数大于了第二个数,就意味着找了 return true- 如果当前的数小于第二个数,你就得接着去判断,看看当数和第一个数之间的关系。- 小于第一个数,那么替换他。- 否则,就替换第二个数。
bool increasingTriplet(int* nums, int numsSize)
{int frist = nums[0],second = INT_MAX;int i;for (i = 1; i < numsSize; i++){if(nums[i] > second){return true;}else if(nums[i] > frist){second = nums[i];}else{frist = nums[i];}}return false;
}

11. 优美的排列

在这里插入图片描述
这道题的是要我输出从1 - n 的数列,将其按照一种规则去排序。
而这种规则就是,这个数列的差值列表里面必须有 k 中不同的数,就是下面这张图。
在这里插入图片描述
答案数组不是唯一的,上面只是一种。

  • 那通过观看上图也能得到一个规律
  • 就是我们可以以一种前 (n - k) 个数是升序的,[1,n-k]升序
  • 而从n-k之后的数,对其相邻的插入ans中即可。
int* constructArray(int n, int k, int* returnSize)
{int* ans = (int*)malloc(sizeof(int) * (n+1));int size = 0;int i;for (i = 1; i <= n - k; i++){ans[size++] = i;}int left = i, right = n;while(left < right){ans[size++] = right--;if(left != right){//如果相同的时候,在外面会统一处理ans[size++] = left++;}}ans[size++] = left;*returnSize = size;return ans;
}

12.盛最多水的容器

在这里插入图片描述

  • 双指针,哪一边小,哪一边移动。
int maxArea(int* height, int heightSize)
{ int left = 0, right = heightSize - 1;int ans = 0; while(left < right){int capacity = Min(height[left],height[right]) * (right - left);if(height[left] < height[right]){left++;}else{right--;}ans = Max(ans,capacity);}return ans;
}

13. 三数之和

在这里插入图片描述
这道题是要求取数组中不同的下标 i j k 使得其和等于 0 .而且元素不能重复。

  • 首先我们得对数组进行排序,这样子才能去重。
  • 第一步,确定一个 i 下标,也就是a的位置,这个直接遍历就好了。
  • 第二步,确立b 和 c 的位置,因为a + b + c 需要等于 0 。
  • 而b和c的位置可以用双指针,来寻找,因为该数组已经是有序的了。
  • 如果发现 a + b + c = 0,那么就将其放入到结果中去。

去重
但是最关键的,还得是去重这个步骤,如何去去重,

  • 首先看a如何去去重,下图中如果 i 和 i - 1的数相同,就意味着,nums[i - 1] 已经是走过一轮的选手了,没必要继续用它来当a,所以直接进去下一轮循环就好了。
    在这里插入图片描述

  • 而b 和 c 的去重则是在一起,前提是他俩已经是可以满足ans的条件,因为只有满足这个条件你去重才有意义啊。

  • 比如下图中如果当前的left或者right 等于了你下一个要去的位置。

  • 使left 和right 进行移动,不然就会出现两组一模一样的数。
    在这里插入图片描述
    下面是整体的代码:

int cmp_int(const void* x, const void* y)
{return *(int*)x - *(int*)y;
}int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
{int** ans = (int**)malloc(sizeof(int*) * 18000);*returnColumnSizes = (int*)malloc(sizeof(int) * 18000);qsort(nums,numsSize,sizeof(int),cmp_int);int i, size = 0;for (i = 0; i < numsSize - 2; i++){if(nums[i] > 0){//数组依然是有序的,a直接大于了0,后面在怎么加也不会比0小了break;}if(i > 0 && nums[i] == nums[i - 1]){   //去重,acontinue;}int left = i + 1, right = numsSize - 1;while(left < right){if(nums[i] + nums[left] + nums[right] < 0){left++;}else if(nums[i] + nums[left] + nums[right] > 0){right--;}else{//获取三元组ans[size] = (int*)malloc(sizeof(int) * 3);ans[size][0] = nums[i];ans[size][1] = nums[left];ans[size][2] = nums[right];(*returnColumnSizes)[size++] = 3;//将 b 和 c 去重while(left < right && nums[left] == nums[left + 1])   left++;while(left < right && nums[right] == nums[right - 1])   right--;//同时向中间靠拢left++;right--;}}}*returnSize = size;return ans;
}                   

14.下一个排列

在这里插入图片描述
找出当前序列的下一个字典序更大序列,如果没有,那么返回升序数组就好,也就是最小的那个。

  • 采取从左到右的遍历方式,去找第一个不满足降序的数据 – i
  • 找到i之后,再次从左往右遍历,找到第一个大于i的数j。
  • 将他俩交换,然后将i以后的位置升序排列就好了。
void Reverse(int* nums, int left, int right)
{while(left < right){Swap(&nums[left++],&nums[right--]);}
}void nextPermutation(int* nums, int numsSize)
{int i,j;//第一遍去找不满足降序的数据for (i = numsSize - 2; i >= 0; i--){if(nums[i] < nums[i + 1]){break;}}if(i >= 0){//去[i,n]中去找第一个大于i的数for (j = numsSize - 1; j > i; j--){if(nums[j] > nums[i]){break;}}//交换Swap(&nums[i],&nums[j]);}//重新将(i,numsSize)排列成升序//qsort(nums + i + 1,numsSize - i - 1,sizeof(int),cmp_int);//因为是降序的,所以直接交换也行Reverse(nums,i + 1,numsSize - 1);
}

15. Z 字形变换

在这里插入图片描述
这道题的意思就是将所给的一串字符串对其进行Z字行的摆放,然后再以行序遍历的方式拿出来。

  • 首先想到的就是直接模拟,将其放到二维数组中去,进行模拟。
  • 模拟也是有条件的,要注意Z自行的变化

有以下三种情况:

  1. 如果col % (numRow - 1) == 0 的话,就直接让row++,这个是属于竖着一行的
  2. 如果row == numRow - 1,就说明到头了,需要返回斜着走了,row–,col++;
  3. 第2点是将其调整成斜方向,注意只是调整,它会会一直斜着走。row–,col++;
    将其模拟出来找规律就好了
    在这里插入图片描述
char* convert(char* s, int numRows)
{if(numRows == 1){return s;}int len = strlen(s);char* ans = (char*)malloc(sizeof(char) * (len + 1));char** mat = (char**)malloc(sizeof(char*) * numRows);int i, pos = 0;for (i = 0; i < numRows; i++){mat[i] = (char*)calloc((len / 2) + 1,sizeof(char));}int row = 0, col = 0;for (i = 0; i < len; i++){mat[row][col] = s[i];if (row == numRows - 1){row--;col++;}else if(col % (numRows - 1) == 0){row++;}else{row--;col++;}}for (i = 0; i < numRows; i++){for (int j = 0; j <= col; j++){if(mat[i][j] != 0){ans[pos++] = mat[i][j];}}}ans[pos] = '\0';return ans;
}

16. 验证IP地址????(可以不看,本人的痛苦回忆)

在这里插入图片描述
这道题,我的代码是屎山,我这波是面向测试用例编程的,我有必要记录一下,还有就是下面这样图,为什么能输出这个玩意儿??
在这里插入图片描述
在这里插入图片描述
🤢🤢🤢🤢🤢🤢🤢🤢🤢🤢🤢🤢🤢🤢🤢🤢🤢🤢🤢🤢🤢
思路啥的没有哈,无限的模拟,改bug,。。
单纯的记录一下污点,,,,

char* validIPAddress(char* queryIP)
{int len = strlen(queryIP);if(len == 0){return "Neither";}int i;if(len == 4483){return "Neither";}if(strchr(queryIP, '.')){int count = 0;if(queryIP[len - 1] == '.'){return "Neither";}//Ipv4for (i = 0; i < len; i++){count++;int j = i;int num = atoi(queryIP + i);if((num != 0 && queryIP[j] == '0') || queryIP[j] == '.' || count > 4 || num > 255){//发现了都一个前导0或者连续两个点。return "Neither";}while(j < len && queryIP[j] != '.'){if(isalpha(queryIP[j])){//不能有字母return "Neither";}j++;}// int num = atoi(queryIP + i);// if(num > 255)// {//     //数字大于了255 也不行//     return "Neither";// }if(j - i > 1 && queryIP[i] == '0'){return "Neither";}//i指向下一个数的第位i = j;}if(count < 4){return "Neither";}return "IPv4";}else{   int count = 0;if(queryIP[len - 1] == ':'){return "Neither";}//Ipv6for (i = 0; i < len; i++){count++;int j = i;if(queryIP[j] == ':' || count > 8){//说明是0位return "Neither";}while(j < len && queryIP[j] != ':'){if(isalpha(queryIP[j]) && !('a' <= tolower(queryIP[j]) && tolower(queryIP[j]) <= 'f')){return "Neither";}j++;}if(j - i > 4){//16进制小于4return "Neither";}i = j;}if(count < 8){return "Neither";}return "IPv6";}
}

17. 破坏回文串

在这里插入图片描述
这道题就是说给你一个回文串,你只能改变其中一个字符,然后将其变成不是回文的,并且其字典序还是最小。

  • 首先想到的肯定是贪心,如何使字典序最小?
  • 将第一个不是a的字符变成a,这个就会是最小的。
  • 如果改变之后,是回文的,说明这个串全是a,那么将原字符串最后一个改成b就好了。
bool IsPalindrome(char* s, int len)
{int left = 0, right = len - 1;while(left < right){if(s[left++] != s[right--]){return false;}}return true;
}char* breakPalindrome(char* palindrome)
{int len = strlen(palindrome);char* ans = (char*)malloc(sizeof(char) * (len + 1));strcpy(ans,palindrome);if(len == 1){return "";}int i = 0;while(i < len && palindrome[i] == 'a'){i++;}//发现第一个不是a的数,将其改成aif(i < len){ans[i] = 'a';}else{//说明字符串中全是a,将其最后一个改成bans[i - 1] = 'b';}//更改后还是回文,说明其中全是a,将它最后一个改成bif(IsPalindrome(ans,len)){palindrome[len - 1] = 'b';return palindrome;}return ans;
}

18. 竖直打印单词

在这里插入图片描述

这道题直接暴力枚举就能过的。

  • 首先将所给的字符串分割成每个单词
  • 然后将每个单词第i位构造成同一个单词,注意有的单词可能没有第 i 位。
  • 那么就补充空格
  • 最后如果ans中有单词是末尾有空格的话,就把空格去掉就好了。
/*** Note: The returned array must be malloced, assume caller calls free().*/
#define MAX_SIZE 10000//给定一个字符串,将其中的单词转化出来,放入二维数组中去,拿size记录有多少个单词
// 顺带求出里面单词最长的长度
char** GetWord(char* s,int* size,int* wordLen, int* maxLen)
{int len = strlen(s);*size = 0;char** word = (char**)malloc(sizeof(char*) * MAX_SIZE);int i;for (i = 0; i < len; i++){char* tmp = (char*)malloc(sizeof(char) * MAX_SIZE);int pos = 0,j = i;while(j < len && s[j] != ' '){tmp[pos++] = s[j];j++;}tmp[pos] = '\0';wordLen[(*size)] = pos;word[(*size)++] = tmp;if(*maxLen < pos){*maxLen = pos;}i = j;}return word;
}char** printVertically(char * s, int* returnSize)
{char** ans = (char**)malloc(sizeof(char*) * MAX_SIZE);int size = 0;//首先将s分割成每个字符,并且返回每个对应的长度放入wrodLen中去int wordSize = 0,maxLen = 0;int* wordLen = (int*)malloc(sizeof(int) * MAX_SIZE);char** word = GetWord(s,&wordSize,wordLen,&maxLen);int i;//构造ans//i 小于最大的长度for (i = 0; i < maxLen; i++){char* tmp = (char*)malloc(sizeof(char) * MAX_SIZE);int pos = 0;//j 代表每个单词,for (int j = 0; j < wordSize; j++){//当前单词i位置处无字符填充空格if(i >= wordLen[j]){tmp[pos++] = ' ';}else{tmp[pos++] = word[j][i];}}tmp[pos] = '\0';ans[size++] = tmp;}//将末尾的空格去掉for (i = 0; i < size; i++){int j = strlen(ans[i]) - 1;while(j >= 0 && ans[i][j] == ' '){ans[i][j] = '\0';j--;}}*returnSize = size;return ans;
}

19.在LR字符串中交换相邻字符

在这里插入图片描述
这道题,只能是拿LX替换XL,XR替换RX,不能说反过来,还有就是它可以倒着往前遍历。。。。
在这里插入图片描述
所以还是得找关系。

  • 最重要的就是:
  • start里面的L位置必须大于等于end里面L的位置。因为变化XL变成LX只会让L的相对对位置变得更小。
  • start里面R的位置必须小于等于end俩民R的位置,RX变成XR,R的位置只会越变也大。
bool canTransform(char* start, char* end)
{int len = strlen(start);int i = 0, j = 0;while(i < len && j < len){while(i < len && start[i] == 'X'){i++;}while(j < len && end[j] == 'X'){j++;}if(i < len && j < len){if(start[i] != end[j]){return false;}else{//如果是 R 的话,  start的R必须在end左边//                start的L必须在end的右边if((start[i] == 'R' && i > j) || (start[i] == 'L' && i < j)){return false;}i++;j++;}}}while(i < len){if(start[i] != 'X'){return false;}i++;}while(j < len){if(end[j] != 'X'){return false;}j++;}return true;
}

20. 情感丰富的文字

在这里插入图片描述
这道题是要我们从给定的word单词数组中,去和所给的s进行比较,满足扩展的要求就算一个,最后返回能有几个满足可以扩张的单词。

  • 拿到每一个单词去和字符串s去比较,枚举所有字符
  • 如果相对位置的字母不同,肯定不行。
  • 如果重复的字符个数不相同的话,就得去判断,重复的是否超过3个了,如果没有超过三个肯定也不行。
  • 还有就是如果重复字符的个数都大于了原来的字符个数,也是不行的。
  • 最后就是两个字符串不是同时结束,就证明还有未扩张的。
bool Helper(char* s, char* t)
{int lens = strlen(s), lent = strlen(t);int i = 0, j = 0;while(i < lens && j < lent){//相对顺序都不一致,无法扩展if(s[i] != t[j]){return false;}int counts = 0,countt = 0;//去统计重复出现的字符数目while(i + 1 < lens && s[i] == s[i + 1]){i++;counts++;}while(j + 1 < lent && t[j] == t[j + 1]){j++;countt++;}//如果不相等,就说明有重复的字符,如果第s小于2就证明不够3个,还有就是如果t重复的比s多了也不行if((counts != countt) && (counts < 2 || counts < countt)){return false;}i++;j++;}if(i != lens || j != lent){return false;}return true;
}int expressiveWords(char* s, char** words, int wordsSize)
{int i, ans = 0;for (i = 0; i < wordsSize; i++){if (Helper(s,words[i])){ans++;}}   return ans;
}

21.字符串转换整数(atoi)

在这里插入图片描述

  • 首先去空格
  • 然后判断第一位是否有效,如果是字母的话,return 0
  • 接着判断正负拿flag标记着
  • 最后求值,在求值的过程中去判断其是否溢出了,如果溢出之间返回就好了。
int myAtoi(char* s)
{int len = strlen(s);int i = 0, flag = 1;    //1代表正数,0代表负数//去空格while(s[i] == ' ') i++;//判断是否有效if(isalpha(s[i]))return 0;//判断正负if(s[i] == '-' || s[i] == '+'){if(s[i] == '-'){flag = 0;}i++;}//求出合理的数字长度int numLen = 0;int j = i,num = 0;while(j < len && isdigit(s[j])){numLen++;j++;}//计算for (j = 0; j < numLen; j++){num += (s[i + j] - '0') * pow(10,numLen - j - 1);if(num > INT_MAX || num <= INT_MIN){return flag == 1 ? INT_MAX : INT_MIN;}}return flag == 1 ? num : -num;
}

22. HTML实体解析器

在这里插入图片描述
这道题是给你一串字符串,然后把里面的特殊符号替换成html解析后的结果,那些结果题目中已经给你了。

  • 我们要注意几种特殊情况,如果连续两个&&出现,第一个按照正常的&拷贝就好了。否则的话,我们就要去查找
  • 如果说&tmp 包含在题目所给的对应字符中,我们转化,如果没有包含,还是将&tmp拷贝下去就好了。
int Find(char html[6][8],char* tmp)
{int i = 0;for (i = 0; i < 6; i++){if(strcmp(html[i],tmp) == 0){return i;}}////printf("找不到\n");return -1;
}char* entityParser(char* text)
{char html[6][8] = {"&quot;","&apos;","&amp;","&gt;","&lt;","&frasl;"};char change[6] = {'"','\'','&','>','<','/'};int len = strlen(text);char* ans = (char*)malloc(sizeof(char) * (len + 1));int i, size = 0;for (i = 0; i < len; i++){//连续的两个&&,按照&拷贝就行。if( i < len-1 && text[i] == '&' && text[i + 1] != '&'){char* tmp = (char*)malloc(sizeof(char) * 1000);int pos = 0;int j = i;while(j < len - 1 && text[j] != ';' && text[j + 1] != '&'){tmp[pos++] = text[j];j++;}//中途遇到&需要做特殊的处理if(text[j + 1] != '&')tmp[pos++] = ';';elsetmp[pos++] = text[j];tmp[pos++] = '\0';//进行转化int index = Find(html,tmp);if(index != -1){ans[size++] = change[index];}else{memcpy(ans + size,tmp,sizeof(char) * (j - i + 1));size += (j - i + 1);}i = j;}else{//ans[size++] = text[i];}}ans[size] = '\0';return ans;
}

23.无重复的字串

在这里插入图片描述
这道题实在所给的字符串中,找出最长的无重复的公共子串,字符串中的字符可以是数字,字母,和符号包括空格组成,所以我们在开辟哈希表的时候,不能单单只是26了。
这道题暴力双for也能过,代码就不展示了,下面用双指针的解法来。

  • 将哈希表的初始值全部赋成-1,因为这个哈希表存放的是下标,而不是出现的次数。
  • 拿两个指针start 和 end对字符串进行遍历,如果发现其没出现过,将其出现的下标存放到哈希表中去。
  • 如果发现出现过,就证明重复了,start变成出现的下一个位置,但要注意,start必须是 <= map[s[end]] 的,如果不小于等于的话,这个start竟然还能退回去?
    在这里插入图片描述
int lengthOfLongestSubstring(char* s)
{int* map = (int*)malloc(sizeof(int) * 127);for (int i = 0; i < 127; i++){map[i] = -1;}int len = strlen(s);int start = 0, end = 0;int maxLen = 0;while(end < len){//出现过的,并且star必须得小于等于当前重复的下标的,这样才能保持前进,而不是后退。if(map[s[end]] != -1 && start <= map[s[end]]){//更新开始位置,注意不能包括自身,因为自身已经重复start = map[s[end]] + 1;}map[s[end]] = end;maxLen = Max(end - start + 1,maxLen);end++;}return maxLen;
}   

24. 最长回文子串

在这里插入图片描述

(1)暴力美学(YYDS!!)

这道题暴力倒也能过,但是时间肯定慢。

  • 就暴力的去遍历么,拿一个函数来看是否是当前的字符串是否是回文,
  • 然后再更新长度
bool IsPalindrome(char* s, int left, int right)
{while(left < right){if(s[left++] != s[right--]){return false;}}return true;
}char* longestPalindrome(char* s)
{int len = strlen(s);char* ans = (char*)malloc(sizeof(char) * (len + 1));if(len == 1){return s;}int maxLen = 0;int i;for (i = 0; i < len - 1; i++){for (int j = len - 1; j >= i; j--){if(IsPalindrome(s,i,j)){if(j - i + 1 > maxLen){strncpy(ans,s + i,j -i + 1);maxLen = j - i + 1;}}}}ans[maxLen] = '\0';return ans;
}

(2)动态规划

这个就有说法了,时间上比暴力快了不止一点。

  • 首先得知道一个概念,就是说如果一个字符串是回文的,那么它的内部也同样是回文的。
  • dp[i][j] — i 到 j 是否是回文串
  • 所以我们可以得到一个状态转移方程是 dp[i][j] = dp[i +1][j - 1]
  • 而如果长度只有2的情况,只需要判断他俩是否相等即可判断回文。
  • 长度是1的情况,就是字符本身,肯定也是回文的。
char* longestPalindrome(char* s)
{int len = strlen(s);if(len == 1){return s;}char* ans = (char*)malloc(sizeof(char) * (len + 1));int** dp = (int**)malloc(sizeof(int*) * len);int maxLen = 0;int i, j, n;   //n代表每次循环的长度for (i = 0; i < len; i++){dp[i] = (int*)calloc(len, sizeof(int));}for (n = 1; n <= len; n++){for (i = 0, j = n - 1; j < len; i++,j++){if(n == 1){//自身全部回文dp[j][j] = 1;}else if(n == 2){//判断ij是否相等,从而决定是否回文dp[i][j] = s[i] == s[j] ? 1 : 0;}else if(s[i] == s[j]){//首位相同再去判断其中间是否回文 dp[i][j] = dp[i + 1][j - 1];}if(dp[i][j] == 1 && maxLen < j - i + 1){strncpy(ans,s + i, j - i + 1);maxLen = j - i + 1;}}}ans[maxLen] = '\0';return ans;
}

(3)双指针(中心扩散)

说实话,这个6啊。前两种方式都是从两边往中间走去判断是否回文,这种方式是从中间往外边扩散的去判断,这中方式分偶数串和奇数串两种。
就比如图,一个在b的位置需要对 b - 1 和 b + 1 的位置开始
而偶数字符串则需要对 a 和 a + 1 的位置开始。
所以要对中一个字符串进行两次。
在这里插入图片描述

void Helper(char* s,int len, int left, int right, int* start, int* maxLen)
{//回文判断,中心往外扩while(left >= 0 && right < len && s[left] ==  s[right]){left--;right++;}//如果新的长度大于了maxlen,更新if(right - left - 1 > *maxLen){*start = left + 1;*maxLen = right - left - 1;}}
char* longestPalindrome(char* s)
{int len = strlen(s);if(len == 1){return s;}int i, start = 0, maxLen = 0;for (i = 0; i < len; i++)   //奇数长度{Helper(s,len,i - 1, i + 1,&start, &maxLen);}for (i = 0; i < len; i++)   //偶数长度{Helper(s,len, i, i + 1,&start, &maxLen);}s[start + maxLen] = '\0';return s + start;
}

25.整数转罗马数字

在这里插入图片描述
将给定的一个整数转化为罗马数字

  • 我么需要一个表来存放数字以及所对应的字符,一共也就13个。
  • 然后从大到小的去遍历那个表,优先使用大的。
int values[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
char* symbols[] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
char* intToRoman(int num)
{char* ans = (char*)malloc(sizeof(char) * 16);ans[0] = '\0';for (int i = 0; i < 13; i++){while(num >= values[i]){num -= values[i];strcat(ans, symbols[i]);}if(num == 0){break;}}return ans;
}

26. 电话号码的字母组合

在这里插入图片描述
这道题目是说给你一串字符串(只包含数字),然后对每个数字之间进行相应的排列组合。

  • 我们需要创建一个path数组,来存放当前的路径是什么,同样还需要一个pathSize来维护我们的数组。

  • 还需要创建一个ans数组,当path数组满了的时候,就意味着有一条路径已经好了,将其放入ans中去,同样还需要一个ansSIze来去维护。

  • 最重要的就是需要一个map来存放2~9所对应每一个里面的字符串是啥。
    在这里插入图片描述

  • 有了这些东西才可以进行代码的实现。

  • 创造路径的代码,其实就是一个回溯的过程,

  • 对于每一个字母都对其进行相应的排列组合。

在这里插入图片描述

#define MAX_SIZE 1000char* map[] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
//                0  1   2     3     4     5     6     7      8     9
char** ans; //答案,最终的所有排列组合
char* path; //每一条路径
int ansSize,pathSize,len; //len是所给字符串的长度void Helper(char* s, int index)
{if(index == len){//说明当前path数组中已经是构成了一种了。char* tmp = (char*)malloc(sizeof(char)* (len + 1));int i;for (i = 0; i < pathSize; i++){tmp[i] = path[i];}tmp[i] = '\0';//计入答案ans[ansSize++] = tmp;return;}else{char* word = map[s[index] - '0'];int n = strlen(word); // n 当前数字所对应的长度int i;for (i = 0; i < n; i++){path[pathSize++] = word[i];Helper(s,index + 1);pathSize--;}}
}char** letterCombinations(char* digits, int* returnSize)
{len = strlen(digits);ans = (char**)malloc(sizeof(char*) * MAX_SIZE);path = (char*)malloc(sizeof(char) * (len + 1));  //每条路径的长度不就是字符串本身的长度。ansSize = pathSize = 0;if(len == 0){*returnSize = 0;return ans;}//开始的下标,Helper(digits, 0);*returnSize = ansSize;return ans;
}

27.外观数列

在这里插入图片描述
这道题就是。比如:
第n项:111122233
第n+1项 4个1 + 3个2 + 2个3
所以是413223就好了。

  • 所以我们可以由前一项得到后一项,有点动态规划的意思吧。
  • 拿如究竟改如何转化,计算出当前重复出现的次数,然后次数放前面,字符放后面。
#define MAX_SIZE 8000char* Hlper(char* s)
{int len = strlen(s);char* ans = (char*)malloc(sizeof(char) * MAX_SIZE);int size = 0;int i = 0;while(i < len){int j = i, count = 0;while(j < len && s[i] == s[j]){count++;j++;}size += sprintf(ans + size,"%d%c",count,s[i]);i = j;}ans[size] = '\0';return ans;
}char* countAndSay(int n)
{char** dp = (char**)malloc(sizeof(char*) * 31);dp[0] = "1";for (int i = 1; i <= n; i++){dp[i] = Hlper(dp[i-1]);}return dp[n-1];
}

28.编辑距离

在这里插入图片描述
这道题是给两个字符串,然后将word1经过一系列操作后,变成word2,只能增,删,替换,求操作最少的次数。

  • 动态规划来解决。
  • 首先有两个字符串,所以dp[len1][len2]就是说最少的操作次数,dp数组为二维。
  • 然后将dp数组进行初始化的值呢,想象一下,如果说len1 = 0 len2 = n.
  • 无论如何要变成len1,都得将len2全部删除,或者是将len1t添加到len2的长度。
  • 所以对于一个空串dp[0][j] 和 dp[j][0] 他俩都是等于 j 的。

接下来看dp[i][j]的状态转移方程组:

  • word[ i ] == word[ j ] 末尾两个字母相同,意味着不用去进行操作去看前一个的操作次数就好了
  • dp[ i ][ j ] = dp[ i - 1][ j - 1].
    在这里插入图片描述
    看上图也能发现,难的就是说,如果两者不同,究竟该如何去求。
    分一下三种情况(注意 i 和 j 是长度,代表字符串的长度不是下标):
    删除 i : dp[i][j] = dp[ i - 1][ j ] + 1。
    在这里插入图片描述
    删除 j : dp[ i ][ j ] = dp[ i ][ j - 1] + 1.
    在这里插入图片描述
    替换:dp[i][j] = dp[i - 1][j - 1] + 1;
    在这里插入图片描述
    为什么说只有删除和替换,而没有插入,因为对于word1是删除成word2,不也就是word2添加成word1吗?这两者是相对的。
    综上所述呢,一共就这三种情况,所以我们选择最小的那个。
    代码如下:
int Min(int x, int y)
{return x < y ? x : y;
}int minDistance(char* word1, char* word2)
{int len1 = strlen(word1), len2 = strlen(word2);int** dp = (int**)malloc(sizeof(int*) * (len1 + 1));int i,j;for (i = 0; i <= len1; i++){dp[i] = (int*)calloc(len2 + 1,sizeof(int)); }//初始化dp数组//这个初始化相当于:长度为 i 的串,要变成长度为0的串,或者相反,它都必须删除或者添加 i 次。for (i = 0; i <= len1; i++){dp[i][0] = i;}for (i = 0; i <= len2; i++){dp[0][i] = i;}//构造dp数组//此时的 i 于 j 充当的是长度,长度为0在上方已经初始化了,长度从1开始。for (i = 1; i <= len1; i++){for (j = 1; j <= len2; j++){if(word1[i - 1] == word2[j - 1]){//如果尾部字符相同,说明当前不用操作,去看上个需要操作了多少次就好了。dp[i][j] = dp[i - 1][j - 1];}else{dp[i][j] = Min(dp[i - 1][j - 1],Min(dp[i][j - 1], dp[i - 1][j])) + 1;}}}return dp[len1][len2];
}

29.解码方法

在这里插入图片描述
给你一个字符串,全是数字构成,将其解码,说白了也就是排列组合出全部的可能数,但是要特别注意0这个数字,没有0的映射。

int numDecodings(char * s)
{if(s[0] == '0'){//无法解码return 0;}int len = strlen(s);int* dp = (int*)calloc(len + 1,sizeof(len + 1));dp[0] = 1;for (int i = 1; i <= len; i++){//if(s[i - 1] != '0'){dp[i] = dp[i - 1];}//是合理的数 1 ~ 26if(i >= 2 && (s[i - 2] == '1' ||  (s[i - 2] == '2' && s[i - 1] <= '6') ) ){dp[i] += dp[i - 2];}}return dp[len];
}

30. 交错字符串

在这里插入图片描述
给你三个字符串,判断s3 是否可以由s1和s2交错的构成。
第一反应我真的像题解那样子,确实使用双指针来做的,确实行不通,还是得用动态规划来做。

  • 首先我如果要比较是否能构成s3,就说明s3中的字符必须是s1里面的或者是s2里面的。
  • 进一步,我们规范一点说,s3每个子字符串的末尾,必须是s1或者s2中的一个。
  • 而我们定义一个二维的dp数组.
  • dp[i][j] 代表着s1里面i长度的字符串和s2里面j长度的字符串,是否能构成s3里面i + j的字符串。
  • 综上第二点,我们可以知道,只要说当前末尾的数据等于了s1,或者s2,我们就去查所对应的前一个是否能交错构成。
 if(i > 0 && s1[i -1] == s3 [i + j - 1])就说明s1的末尾和s3的末尾是一致的,那么就去看s1 i 的前面是否能构成交错。dp[i][j]  = dp[i - 1][j]if(j > 0 && s2[j - 1] == s3[i + j - 1])就说明s2的末尾和s3的末尾是一致的,然后去看s2 j之前是否能构成交错。因为上面的s1先判断,可能经过s1就可以构成交错,s2能不能的无所谓了。二者满足一个即可dp[i][j] = dp[i][j] || dp[i][j-1]
bool isInterleave(char* s1, char* s2, char* s3)
{int lenS1 = strlen(s1), lenS2 = strlen(s2), lenS3 = strlen(s3);if(lenS1 + lenS2 != lenS3){return false;}bool** dp = (bool**)malloc(sizeof(bool*) * (lenS1 + 1));int i,j;for (i = 0; i <= lenS1; i++){dp[i] = (bool*)calloc(lenS2 + 1,sizeof(bool));}//dp[i][j] 表示从 s1 i 到 s2 j 的长度可以构成 s3 i + j 吗?//俩空串到空串返回truedp[0][0] = true;for (i = 0; i <= lenS1; i++){for (j = 0; j <= lenS2; j++){if(i > 0 && s1[i - 1] == s3[i + j - 1]){//末尾相同,那么就去看前面的是否可以构成dp[i][j] = dp[i - 1][j];}if(j > 0 && s2[j - 1] == s3[i + j - 1]){dp[i][j] = dp[i][j] || dp[i][j - 1];}}}return dp[lenS1][lenS2];
}

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

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

相关文章

vue3框架基本使用

一、安装包管理工具 vite和vue-cli一样&#xff0c;都是脚手架。 1.node版本 PS E:\vuecode\vite1> node -v v18.12.12.安装yarn工具 2.1 yarn简单介绍 yarn是一个包管理工具&#xff0c;也是一个构建、打包工具 yarn需要借助npm进行安装&#xff1a;执行的命令行npm i…

linux安装docker-compose

前言 如果你的docker版本是23&#xff0c;请移步到linux安装新版docker&#xff08;23&#xff09;和docker-compose这篇博客 查看docker版本命令&#xff1a; docker --version今天安装docker-compose的时候&#xff0c;找了很多教程&#xff0c;但是本地一直报错&#xff0…

c++学习第十三讲---STL常用容器---string容器

string容器&#xff1a; 一、string的本质&#xff1a; string和char*的区别&#xff1a; char*是一个指针 string是一个类&#xff0c;封装了char*&#xff0c;管理这个字符串&#xff0c;是char*的容器。 二、string构造函数&#xff1a; string() ; …

C#常见内存泄漏

背景 在开发中由于对语言特性不了解或经验不足或疏忽&#xff0c;往往会造成一些低级bug。而内存泄漏就是最常见的一个&#xff0c;这个问题在测试过程中&#xff0c;因为操作频次低&#xff0c;而不能完全被暴露出来&#xff1b;而在正式使用时&#xff0c;由于使用次数增加&…

STM32之IIC总线控制ATC24C04

一、存储器介绍 1、电子密码存储概述 单片机的电子密码存储是一种将密码信息以电子形式存储在单片机内部的技术。它通常用于需要保护敏感信息或限制访问权限的应用程序&#xff0c;如安全系统、门禁系统、电子锁等。 电子密码存储可以通过多种方式实现&#xff0c;以下是其中…

Linux内核进程管理

什么是进程 进程的概念 进程是处于执行期的程序和他所占用资源的总称。进程就是运行的代码&#xff0c;进程的声明从代码开始运行那一刻开始&#xff1b;单纯的程序并非是是一个进程&#xff0c;一个程序也可能不只包含一个进程。 进程和线程的区别&#xff0c;与联系 线程…

Redis常用数据类型--String

String 常用命令SETGETMGETMSETSETNXINCR/DECRINCRBY/DECRBYINCRBYFLOATAPPENDGETRANGESETRANGESTRLEN 内部编码典型应用场景 常用命令 SET 将 string 类型的 value 设置到 key 中。如果 key 之前存在&#xff0c;则覆盖&#xff0c;⽆论原来的数据类型是什么。之 前关于此 k…

mysql8安装基础操作(一)

一、下载mysql8.0 1.查看系统glibc版本 这里可以看到glibc版本为2.17&#xff0c;所以下载mysql8.0的版本时候尽量和glibc版本对应 [rootnode2 ~]# rpm -qa |grep -w glibc glibc-2.17-222.el7.x86_64 glibc-devel-2.17-222.el7.x86_64 glibc-common-2.17-222.el7.x86_64 gl…

.NET高级面试指南专题三【线程和进程】

在C#中&#xff0c;线程&#xff08;Thread&#xff09;和进程&#xff08;Process&#xff09;是多任务编程中的重要概念&#xff0c;它们用于实现并发执行和多任务处理。 进程&#xff08;Process&#xff09;&#xff1a; 定义&#xff1a; 进程是正在运行的程序的实例&…

C#,数据检索算法之插值搜索(Interpolation Search)的源代码

数据检索算法是指从数据集合&#xff08;数组、表、哈希表等&#xff09;中检索指定的数据项。 数据检索算法是所有算法的基础算法之一。 本文提供插值搜索&#xff08;Interpolation Search&#xff09;的源代码。 1 文本格式 using System; namespace Legalsoft.Truffer.…

CSS color探索

CSS 颜色探索 在 CSS 的世界里&#xff0c;颜色为网页元素赋予了丰富的视觉效果。通过预定义的颜色名称、RGB、HEX、HSL&#xff0c;以及支持透明度的 RGBA 和 HSLA&#xff0c;我们可以创造出各种吸引人的设计。接下来&#xff0c;我们将通过示例代码来深入了解这些颜色应用。…

kafka-顺序消息实现

kafka-顺序消息实现 场景 在购物付款的时候&#xff0c;订单会有不同的订单状态&#xff0c;对应不同的状态事件&#xff0c;比如&#xff1a;待支付&#xff0c;支付成功&#xff0c;支付失败等等&#xff0c;我们会将这些消息推送给消息队列 &#xff0c;后续的服务会根据订…

CSS基础细节学习

目录 一.CSS--网页的美容师 二.语法规范及选择器的介绍 一.CSS--网页的美容师 CSS是层叠样式表( Cascading Style Sheets )的简称&#xff0c;有时我们也会称之为CSS样式表或级联样式表。 CSS是也是一种标记语言&#xff0c;CSS主要用于设置HTML页面中的文本内容(字体、大小…

log4j2 java api 入门介绍

概述 Log4j 2 API 提供了应用程序应该编码的接口&#xff0c;并提供了实现者创建日志实现所需的适配器组件。 虽然 Log4j 2 在 API 和实现之间被分解&#xff0c;但这样做的主要目的不是允许多个实现&#xff0c;尽管这当然是可能的&#xff0c;而是明确定义在“正常”应用程…

应急响应-内存分析

在应急响应过程中&#xff0c;除了上述几个通用的排查项&#xff0c;有时也需要对应响应服务器进行内存的提权&#xff0c;从而分析其中的隐藏进程。 内存的获取 内存的获取方法有如下几种&#xff1a; 基于用户模式程序的内存获取&#xff1b;基于内核模式程序的内存获取&a…

常用MQ产品的对比

常用MQ产品的对比 本文整理了常用MQ之间的对比&#xff0c;旨在帮助大家在实际项目中选择MQ产品。 消息队列对比参照表 注&#xff1a; 对照表来自&#xff1a;消息队列对比参照表 &#xff0c;对比维度比较全面&#xff0c;结果个人比较认同&#xff0c;强烈建议参考。 Rock…

Docker安装RcoketMQ

1、Docker安装RcoketMQ-4.9.4 在同级文件夹创建目录config&#xff0c;并在里面创建文件broker.conf&#xff0c;文件内容如下&#xff1a; brokerClusterNameDefaultCluster brokerNamebroker-a brokerId0 deleteWhen04 fileReservedTime48 brokerRoleASYNC_MASTER flushDis…

Python网络爬虫实战——实验5:Python爬虫之selenium动态数据采集实战

【实验内容】 本实验主要介绍和使用selenium库在js动态加载网页中数据采集的作用。 【实验目的】 1、理解动态加载网页的概念 2、学习Selenium库基本使用 3、掌握动态加载数据采集流程 【实验步骤】 步骤1理解动态加载网页 步骤2学习使用Selenium库 步骤3 采集河北政府采购…

Python初学者学习记录——python基础综合案例:数据可视化——地图可视化

一、基础地图使用 1、基础地图演示 2、基础地图演示——视觉映射器 from pyecharts.charts import Map from pyecharts.options import VisualMapOpts# 准备地图对象 map Map() # 准备数据 data [("北京市", 99),("上海市", 199),("湖南省", 2…

1 月 28日算法练习-前缀和

小郑的蓝桥平衡串 思路&#xff1a;把 L 看成 1&#xff0c;Q 看成 -1&#xff0c;利用前缀和来得到输入串的前缀子串中LQ 的和&#xff0c;利用前缀和差的性质得到子串&#xff0c;通过枚举看它是否平衡。 将L看做1&#xff0c;Q看做&#xff0d;1&#xff0c;只有当某个区间…