前言
分享一些刷题中遇到的又多种解法的题目
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"); }
结语
这个系列的文章具体几道题没有标准,就差不多我写四五道题就发一篇
希望这篇文章对你有帮助,我们下次见~