【C语言】题目的多种解法分享3

简介: 【C语言】题目的多种解法分享3

前言

分享一些刷题中遇到的又多种解法的题目

1:HJ10 字符个数统计

题目

题目链接

解法:

解法1:使用qsort

使用qsort进行排序,再遍历数组,对数组的每个元素判断是否相等,相等将其赋值为0~127范围以外的数字,

之后再遍历一遍数组判断,看其是否为范围外的数字即可

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int cmp(const void* p1, const void* p2)
{
  return *(char*)p1 - *(char*)p2;
}
int main()
{
  char arr[501] = { 0 };
  scanf("%s", &arr);
  qsort(arr, strlen(arr), sizeof(char), cmp);
  int i = 0;
  int sum = 0;
  for (i = 0; i < strlen(arr); i++)
  {
    if (arr[i] == arr[i + 1])
    {
      arr[i] = -1;
    }
  }
  for (i = 0; i < strlen(arr); i++)
  {
    if (arr[i] != -1)
    {
      sum++;
    }
  }
  printf("%d\n", sum);
  return 0;
}

解法2:创建两个数组

创建两个数组,一个用于输入字符串

另外再开辟一个数组,元素个数为128:对应着0~127共128个数字

剩下的解释我写在了注释里

#include <stdio.h>
#include <string.h>
int num=0,len,i,j,k,asc;
int tmp[128]={0};
char str[400];
int main()
{
    gets(str);
    len=strlen(str);
    for(i=0;i<len;i++)
    {
        asc=(int)str[i];//将字符强制转换成它的ASCII码值,赋值给asc
        if(tmp[asc]==0)//将asc作为下标,
        //如果数组中,该下标处的元素为0,那么asc就在0~127之间,也就是str[i]符合条件
        {
            tmp[asc]=1;
            num++;
        }
    }
    printf("%d",num);
    return 0;
}

太神奇了,完全没想到这种方法。

2:169. 多数元素

题目

题目链接

解法1:遍历

遍历数组,计算某个元素在数组中出现的次数,判断是否大于n/2

int majorityElement(int* nums, int numsSize)
{
  int i = 0;
  int j = 0;
  int sum = 0;
  for (i = 0; i < numsSize; i++)
  {
    for (j = 0; j < numsSize; j++)
    {
      if (nums[i] == nums[j])
      {
        sum++;
      }
      if (sum > (numsSize / 2))
      {
        return nums[i];
      }
    }
  }
  return 0;
}

解法2:使用qsort

这道题其实求的就是众数(出现次数最多的数字),所以我们只需要将数组进行排序,再返回n/2下标处的元素即可

注意:

因为题目已经明确说明:

假设数组是非空的,并且给定的数组总是存在多数元素。

所以我们不需要考虑是否该元素出现次数不足n/2

当然,我们也可以将取出的这个元素和排序后的数组首元素进行比较,相等则为众数

代码:
int cmp(const void* p1, const void* p2)
{
  return *(int*)p1 - *(int*)p2;
}
int majorityElement(int* nums, int numsSize)
{
  qsort(nums, numsSize, sizeof(int), cmp);
  return nums[numsSize / 2];
}

3:238. 除自身以外数组的乘积

题目

题目链接

解法

解法1:创建两个数组计算左边和右边

创建两个数组:

int left[numsSize];
  int right[numsSize];

注意:

这里使用的是变长数组,VS不支持这种写法

left数组用于记录i左侧的元素之积

left[0] = 1;
for (int i = 1; i < numsSize; i++)
{
  left[i] = left[i - 1] * nums[i - 1];
}

right数组用于记录i右侧的元素之积

right[numsSize - 1] = 1;
  for (i = numsSize - 1 - 1; i >= 0; i--)
  {
    right[i] = right[i + 1] * nums[i + 1];
  }

注意:

这里要从最右侧开始,

最后再利用循环将两个数组乘在一起

for (i = 0; i < numsSize; i++)
{
  returnNums[i] = left[i] * right[i];
}
代码
int* productExceptSelf(int* nums, int numsSize, int* returnSize)
{
  int left[numsSize];
  int right[numsSize];
  int i = 1;
  left[0] = 1;
  for (i = 1; i < numsSize; i++)
  {
    left[i] = left[i - 1] * nums[i - 1];
  }
  right[numsSize - 1] = 1;
  for (i = numsSize - 1 - 1; i >= 0; i--)
  {
    right[i] = right[i + 1] * nums[i + 1];
  }
  *returnSize = numsSize;
  int* returnNums = (int*)malloc(sizeof(int) * numsSize);
  for (i = 0; i < numsSize; i++)
  {
    returnNums[i] = left[i] * right[i];
  }
  return returnNums;
}

解法2:创建一个数组遍历

先创建两个变量分别从左侧和右侧开始乘以给定的数组

之后,再赋给arr

int* productExceptSelf(int* nums, int numsSize, int* returnSize)
{
  int i = 0;
  int *arr = (int*)malloc(sizeof(int)* numsSize);
  for(i = 0; i < numsSize; i++)
  {
        arr[i] = 1;
    }
  int pre = 1;
  int suf = 1;
  for (i = 1; i < numsSize; i++)
  {
    pre *= nums[i - 1];
    suf *= nums[numsSize - i];
    arr[i] *= pre;
    arr[numsSize - 1 - i] *= suf;
  }
  *returnSize = numsSize;
  return arr;
}

4:JZ65 不用加减乘除做加法

题目

题目链接

解法

解法1

int Add(int num1, int num2)
{
  int m = 0;
  int n = 0;
  m = (num1 & num2);
  m <<= 1;
  n = num1 ^ num2;
  while (n & m)
  {
    num1 = m;
    num2 = n;
    m = (num1 & num2);
    m <<= 1;
    n = num1 ^ num2;
  }
  return m | n;
}
解释:

m是二者与运算之后的结果,都是需要进位的,

所以m<<1

n是二者中不同的位,也就是不需要进位的

当m&n不为0,也就是进位没进干净之前,都要在while循环中重复上面的操作,

最后返回m | n,就是结果

解法2

int Add(int num1, int num2) 
{
  return (num1 | num2) + (num1 & num2);
}
num1 | num2

二者相或,结果是所有非0的位之和

num1 & num2

二者相与,是之前或运算中漏算的1

二者相加得出的就是二者的和

解释:

因为二进制中,不是1就是0

先用或运算,找出所有的1

再通过与运算,找出漏下的1

5:倒序输出数字

题目

输入一个数字,倒叙打印这个数字

如,输入123

打印出321

解法

解法1:当成字符串输入

#include <stdio.h>
int main()
{
    char str[32] = {0};
    scanf("%s",str);
    //gets(str);
    for(int i=strlen(str)-1;i>=0;i--)
    {
        printf("%c",str[i]);
    }
    printf("\n");
}

可以通过 scanf(“%s”) 把输入的数字当做一个字符串进行接收,然后直接从后向前倒序输出。

解法2:当成数字输入

#include<stdio.h>
int main(){
    int num = 0;
    scanf("%d\n",&num);
    if(num == 0) 
    { 
      printf("%c",'0');
    }
    while(num != 0)
    {
        printf("%c",num%10+'0');
        num/=10;
    }
    printf("\n");
}

结语

这个系列的文章具体几道题没有标准,就差不多我写四五道题就发一篇

希望这篇文章对你有帮助,我们下次见~


相关文章
|
4月前
|
C语言
C语言:数组和指针笔试题解析(包括一些容易混淆的指针题目)
C语言:数组和指针笔试题解析(包括一些容易混淆的指针题目)
|
4月前
|
存储 C语言 C++
C语言------------指针笔试题目深度剖析
C语言------------指针笔试题目深度剖析
38 1
|
9月前
2.C语言题目---字符串左旋
2.C语言题目---字符串左旋
66 1
|
1月前
|
存储 编译器 C语言
【C语言】指针练习题目
【C语言】指针练习题目
|
9月前
|
存储
1.C语言题目---指针类(基础)
1.C语言题目---指针类(基础)
51 1
|
3月前
|
测试技术 C语言
数据结构学习记录——树习题—Tree Traversals Again(题目描述、输入输出示例、解题思路、解题方法C语言、解析)
数据结构学习记录——树习题—Tree Traversals Again(题目描述、输入输出示例、解题思路、解题方法C语言、解析)
36 1
|
4月前
|
算法 编译器 API
C语言易混淆、简单算法、结构体题目练习、常见关键字总结-1
C语言易混淆、简单算法、结构体题目练习、常见关键字总结
|
3月前
|
C语言
c语言循环题目
c语言循环题目
|
4月前
|
C语言
PTA 浙大版《C语言程序设计(第3版)》题目集 习题8-4 报数 (20分)
PTA 浙大版《C语言程序设计(第3版)》题目集 习题8-4 报数 (20分)
|
4月前
|
C语言
C语言 浙大版《C语言程序设计(第3版)》题目集 练习8-8 移动字母 (10分)
C语言 浙大版《C语言程序设计(第3版)》题目集 练习8-8 移动字母 (10分)