简单记录牛客top101算法题(初级题C语言实现)判断回文字符串 && 反转字符串 && 合并两个有序的数组

1. 判断是否为回文字符串

  给定一个长度为 n 的字符串,请编写一个函数判断该字符串是否回文。如果是回文请返回true,否则返回false。
  字符串回文指该字符串正序与其逆序逐字符一致。

//示例
输入:"ranko"
返回值:false

1.1 整体思路

  1. 统计字符串个数。
  2. 遍历字符串,首尾依次比较字符是否相等
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
bool judge(char* str ) {
   int n = 0;              //统计字符串个数
   n = strlen(str);        //计算字符串个数
   char *p1 = &str[0];      //声明开始指针
   char *p2 = &str[n-1];    //声明结束指针,数组索引是从0开始的
    for(int i = 0; i < n / 2; i++) {
        if (*(p1 + i) != *(p2 - i)) {
            return false;
        }
     }
     return true;
  }
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
bool judge(char* str ) {
	int n = 0;
       while (*(str + n) != '\0') {     //统计字符串的个数
        n++;
    }
  for (int j = 0; j < n /2; j++) {                         //只取一半的值遍历       
       if( *(str + j) !=  *(str + n - 1- j) ){            //对称判断字符是否相等 
             return  false;
           } 
        }
     return  true;
}

备注:
  以字符串数组5个元素为例子,5 / 2 = 2,i能取到的值就是0和1(前两个元素),所以从尾开始算起的话,也是取了最后一个元素和倒数第一个元素(后两个元素);
  以字符串数组6个元素为例子,5 / 2 = 3,i能取到的值就是0和1和2(前三个元素),所以从尾开始算起的话,也是取了最后一个元素、倒数第一个元素和倒数第二个元素(后三个元素);

1.2 小结

  1. 声明字符和字符串。
//声明字符
 char  c = 'A';

//声明字符串
 char  str[] = "abadon";      //声明字符串就是字符数组

2.数组指针

char  str[] = "abadon"; 
  str                 //数组名称代表数组元素首地址,即指针
  str[0] = *(str + 0);
  str[i] = str[0 + i] = *(str + i);      //[]和*相当于是等价的

3.统计字符串大小

//使用strlen()函数
int n = 0;              //统计字符串个数
n = strlen(str);        //计算字符串个数

//使用while循环统计
int n = 0;
   while (*(str + n) != '\0') {     //统计字符串的个数
       n++;
    }

4.布尔数据类型打印

   //c语言中的bool型就是0和1,因此可以用%d输出
   bool  b = true;
   printf("%d\n",b)


2. 反转字符串

  写出一个程序,接收一个字符串,然后输出该字符串反转后的字符串。

输入:"abcd"
返回值:"dcba"

2.1 整体思路

  1. 统计字符串个数。
  2. 遍历字符串,首尾依次互换字符位置。
#include <stdlib.h>
#include <string.h>
char* solve(char* str ) {
    // write code here
    int n = 0;
    n = strlen(str);
    // char* str1 = (char*)malloc(sizeof(char) * n );       //申请动态数组
    char c;            //声明中间变量

    for (int i = 0; i < n / 2 ; i++) {
           c = *(str + i);         //中间变量接收前面字符
          *(str + i) = *(str + n -1 -i);   //前面字符接收后面字符
          *(str + n -1 -i) = c;     //后面字符接收中间变量,也就是前面字符
    }
    return str;
}

整体思想和上面一题思想差不多。

3. 合并两个有序的数组


      在这里插入图片描述
  自己的思路:根据提交后报的错误,可以把具体情况分为一下几种,先判断B数组是否为空,如果为空,则不需要任何其他的操作;如果不为空,再分为以下三种情况进行讨论:

  1. 如果A数组的最小值大于等于B数组的最大值(就是4,5,6 1,2,3这种情况),只需要把A数组的值移动到后面,把B数组的值移动到A数组开始值的位置即可;
  2. 如果A数组的最大值小于等于B数组的最小值(就是1,2,3 4,5,6这种情况),只需要在A数组的后面追加B数组的值即可;
  3. 如果除上面两种情况外,都归属于第三种情况(如1,7,9 2,8,5这种情况),需要遍历B数组,与A数组中的每一个值进行比较,如果B数组的元素值比A数组的值小,则交换两者的位置,这样一圈下来,A是前面m个数的顺序已经排好了,B数组的顺序没有排列,所以只需要排列B数组的顺序即可(这里是使用了选择排序)。
      初始值: 1 7 9 2 8 5
      第一次: 1 2 9 7 8 5
      第二次: 1 2 7 9 8 5
      第三次: 1 2 7 8 9 5
      第四次: 1 2 7 5 9 8
      第五次: 1 2 5 7 8 9
/**
 *
 * @param A int整型一维数组
 * @param ALen int A数组长度
 * @param B int整型一维数组
 * @param BLen int B数组长度
 * @return void
 */
#include <stdio.h>
#include <string.h>
void merge(int* A, int ALen, int m, int* B, int BLen, int n) {

    int c = 0;
    int isEmpty = 1;
    for (int i = 0; i < n; i++) {
        if (B[i] != 0) {
            isEmpty = 0;         //代表非空
            break;
        }
    }
    if ( isEmpty == 0 ) {
        if (A[0] >= B[n-1]) {                            //如果A的最小大于B的最大值(就是4,5,6   1,2,3这种情况),索引一定要减去1
            //先把前面的移出去,移到后面去
            for ( int k = 0 ; k < m;  k++) {
                A[m + k] = A[k];                     //A[4] = A[0]
            }
            //先把后面的移出去,移到后面去
            for (int k = 0 ; k < n;  k++) {
                A[k] = B[k];
            }
        } else if (A[m - 1] <= B[0]) {                    //如果A的最大值小于B的最小值(就是1,2,3   4,5,6这种情况),
            for ( int k = 0 ; k < n;  k++) {
                A[m + k] = B[k];                    //A[4] = A[0]
            }
            printf("value0 = %d\r\n",100);
        } else {                                        //这里以1,2,3  2,5,6为例        先比较B[0]的大小
            for (int i = 0; i < n; i++) {               //遍历B中的每一个元素
                for (int j = 0; j < m; j++) {        //遍历A中的元素
                    if (A[j] > B[i]) {               //A中的元素值大于B中的原始,换两者的位置
                        c = A[j];                    //接收A[j]的值
                        A[j] = B[i];
                        B[i] = c;
                    }
                }
            }
            printf("value1 = %d\r\n",100);
            //遍历数组B,把B排一下
            for (int h = 0; h < n; h++) {               //使用冒泡排序法
                for (int l = h + 1; l < n; l++) {           //
                    if ( B[h] >  B[l]) {
                        c = B[h];
                        B[h] = B[l];
                        B[l] = c;
                    }
                }
            }
            //拼接整个数组
            for ( int k = 0 ; k < n;  k++) {         //数组前半部分不动,把B的值放到A的后面
                A[m + k] = B[k];                    //A[4] = A[0]
            }
        }
    }
}

  看大佬的思路:
1.从确定最大值开始,以B和A的尾索引来计,逐个比较,如果大就放到新数组A的尾部,依次进行,这样就不用遍历进行数组元素换位置了。

int len =  m + n -1;     //数组总长度
int endA = m - 1;        //数组A的长度
int endB = n - 1;        //数组B的长度
 while (endA >= 0 && endB >= 0) {        //A和B都存在的情况

        if (A[endA] >= B[endB]) {
            A[len] = A[endA];
            len--;
            endA--;
        }else {
            A[len] = B[endB];
            len--;
            endB--;
        }
}
  while (endB >= 0){                  //A数组不存在情况或者B数组不存在这两种情况都包含了
       A[len] = B[endB];
       len--;
       endB--;
 }

   2.先将B数组的全部拼接到A数组的后半部分,再对整体进行冒泡排序。

for (int i = 0; i < n; i++) {    //拼接两个数组
    A[m + i] = B[i];
}
for (int j = 0; j < m + n ; j++) {              //冒泡排序
   for (int k = 0; k < m + n - 1 - j; k++ ){ 
    if (A[k]  > A[k+1]) {
        c = A[k];
        A[k] = A[k+1];
        A[k+1] =c;
    }
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值