1.打印空格和星号的规律
#include<stdio.h> int main() { int n=0; while(~scanf("%d",&n)) { //上半部分n+1行 for(int i=1;i<=n+1;i++) { //空格 for(int j=1;j<=n+1-i;j++) { printf(" "); } //星号 for(int j=1;j<=i;j++) { printf("*"); } printf("\n"); } //下半部分n行 for(int i=1;i<=n;i++) { //空格 for(int j=1;j<=i;j++) { printf(" "); } //星号 for(int j=1;j<=n+1-i;j++) { printf("*"); } printf("\n"); } } return 0; }
这题的启示:
可以把两个空格作为一次性输出,只要for循环里的判断条件你好写,怎么样都行!!
学习到牛客网:原来可以通过鼠标可以查看空格有多少个!!!
我的做题感悟:
分为上下两部分,每行就是空格和星号组成也是老生常谈了
形成自己的风格:for(int i=1;i<=N;i++)这样的题从1开始,然后<=某一个数
找规律,空格和星号的循环判断条件:越来越多,用i,然后加减某一个数,越来越少,用n-i,然后加减某一个数,这个某一个数可以通过第一个外层循环的i带入来知晓。
2.别样的多组输入
#include<stdio.h> int main() { int score=0;//分数(整数) int max=0; int min=100;//最小值先给最大的 int count=0;//计数器,7个一组 int sum=0;//7个整数的和 while(scanf("%d",&score)!=EOF)//一次输入一个 { if(max<score) max=score; if(min>score) min=score; sum+=score; count++; if(count==7)//7个为一组,够了7个重新初始化 { printf("%.2lf\n",(sum-min-max)/5.0);//格式输出:换行 max=0; min=100; sum=0; count=0; } } return 0; }
这题的提示:
对于多组输入,且是一组输入多个数据,可能大多数人想到的做法是:对于每一组数据一次性输完
但是这样即不美观,当数据多了就...
3.左旋字符串的多种解法
题目:
实现一个函数,可以左旋字符串中的k个字符。
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
方法1:保存前移
#include<string.h> void LeftRound(char* str, int k) { int len = strlen(str); k = k%len; for (int i = 0; i < k; i++) { char temp = str[0]; for (int i = 1; i <= len - 1; i++) { str[i - 1] = str[i]; } str[len - 1] = temp; } } int main() { char str[20] = "hello world"; int k = 0; scanf("%d", &k); LeftRound(str, k); printf("%s\n", str); return 0; }
启发:
k=k%len;提高效率
方法2:临时数组
#include<stdlib.h> void LeftRound(char* str, int k) { int len = strlen(str); k = k % len; char* temp = (char*)malloc(sizeof(len + 1)); if (temp == NULL) { perror(temp); return -1; } strcpy(temp, str + k); strncat(temp, str, k); strcpy(str, temp); } int main() { char str[20] = "hello world"; int k = 0; scanf("%d", &k); LeftRound(str, k); printf("%s\n", str); return 0; }
方法3: 三次反转
void Rotate(char* str, int left, int right) { while (left < right) { char temp = str[left]; str[left] = str[right]; str[right] = temp; left++; right--; } } void LeftRound(char* str, int k) { int len = strlen(str); k = k % len; Rotate(str, 0, k - 1); Rotate(str, k, len - 1); Rotate(str, 0, len - 1); } int main() { char str[20] = "hello world"; int k = 0; scanf("%d", &k); LeftRound(str, k); printf("%s\n", str); return 0; }
rotate:旋转
reverse:反转
4.数组中出现次数超过一半的数字
方法1:哈希表法
本题涉及到<数组元素,出现次数>之间的对应映射关系,这种方法应该不难想到,把数组元素出现的次数存到一个标记数组map里,然后遍历一遍map标记数组,找到次数>half的元素就行!
int MoreThanHalfNum_Solution(int* numbers, int numbersLen ) { // write code here int map[10000]={0}; int half=numbersLen/2; for(int i=0;i<numbersLen;i++) { map[numbers[i]]++; } for(int i=0;i<numbersLen;i++) { if(map[numbers[i]]>half) { return numbers[i]; } } return 0; }
时间复杂度:O(n)
空间复杂度:O(1)
方法2:排序中值法
由于题目给定输入的数组"一定非空",也就是numbersLen>=1,还给定"且保证有解",那么数组中一定存在一个出现次数超过一半的数组元素。
那么如果我们给数组先进行排序,然后取排完序的数组的中间元素,那一定就是目标值!
也就是快速排序+返回numbers[mid]的代码,简单!不写!
有人可能又要问数组元素取numbers[mid]的时候是否要分奇偶,不需要!(因为蓝色标注)
时间复杂度:O(nLogN)
空间复杂度:O(1)
方法3:消除异值法
只要我们把数组元素不同的两个值给消除掉,因为一定存在一个次数超过数组一半的元素,
所以最后留下来的那个数组值一定是目标值!
int MoreThanHalfNum_Solution(int* numbers, int numbersLen ) { if(numbers==NULL) return -1; int time=1; int target=numbers[0]; for(int i=1;i<numbersLen;i++) { if(time==0) { target=numbers[i]; time=1; continue; } if(target==numbers[i]) { time++; } else { time--; } } return target; return 0; }