c语言---刷题02

1.输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数

比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999

int* printNumbers(int n, int* returnSize )
{
    *returnSize = pow(10, n) - 1;    //确定最大的数字
    int *arr = (int *)malloc(sizeof(int)*(*returnSize));   //申请足够大小的空间
    for (int i = 0; i < *returnSize; i++) 
    {
        arr[i] = i+1;    //下标从0开始,而数值从1开始
    } 
    return arr;
}
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param n int整型 最大位数
 * @return int整型一维数组
 * @return int* returnSize 返回数组行数
 *
 * C语言声明定义全局变量请加上static,防止重复定义
 */
static int arr[100001];
int* printNumbers(int n, int* returnSize ) {
    int max=1;
    for(int i=0;i<n;i++)
    {
        max*=10;
    }
    int i=0;
    for(i=0;i<max;i++)
    {
        arr[i-1]=i;
    }
    *returnSize=i-1;
    return arr;
}

2.根据输入的日期,计算是这一年的第几天

#include <stdio.h>
int isleapyear(int year)
{
    if(0 == year%4)
    {
        if(0 == year%100 && 0 != year%400)
            return 0;
        else
            return 1;
    }
    else
        return 0;
}

int main()
{
    int daynum_of_leapyear[12] = {31,29,31,30,31,30,31,31,30,31,30,31};
    int daynum_of_commonyear[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
    
    int year,month,day;
    scanf("%d", &year);
    scanf("%d", &month);
    scanf("%d", &day);   
    int daynum = 0;
    if(1 == isleapyear(year))
    {
        for(int i =0; i<month-1; i++)
        {
            daynum += daynum_of_leapyear[i];
        }
    }
    else
    {
        for(int i =0; i<month-1; i++)
        {
            daynum += daynum_of_commonyear[i];
        }
    }
    
    daynum += day;
    printf("%d",daynum);
    return 0;
}

3.求输出结果

#include <stdio.h>
#define N 2
#define M N + 1
#define NUM (M + 1) * M / 2
int main()
{
    printf("%d\n", NUM);
    return 0;
}

宏只是替换,替换后NUM的样子是(2+1+1)*2+1/2,计算得8

#include<stdio.h>
int main()
{
    char s[] = "\\123456\123456\t";
    printf("%d\n", strlen(s));
    return 0;
}

注意:\\ 表示字符'\',\123表示字符'{',\t表示制表符,这些都是一个字符
结果是12

下面3段程序代码的效果一样吗

int b;
(1)const int *a = &b;
(2)int const *a = &b;
(3)int *const a = &b;

const在*的左边,则指针指向的变量的值不可直接通过指针改变(可以通过其他途径改变);在*的右边,则指针的指向不可变。简记为"左定值,右定向",(1)和(2)const都在*的左边,(3)中const在*的右边,
(1)=(2)

#include <stdio.h>
int i;
void prt()
{
    for (i = 5; i < 8; i++)
    printf("%c", '*');
    printf("\t");
} 
int main()
{
    for (i = 5; i <= 8; i++)
        prt();
    return 0;
}

全局变量i,在main()中修改为5,第一次在prt()中执行循环输出三次'*',i被修改为8,回到main()中第二次调用prt()时,i<8为假,循环结束没输出,执行一次print("\t"),再次回到主函数后i++变为9,i<=8为假,循环结束;

***

int main()
{
    int a=3;
    printf("%d\n",(a+=a-=a*a));
    return 0;
}

a+=a-=a*a等价于a=a+(a=a-a*a),即先计算a=a-a*a,所以此时a的值为3-3*3=-6,再计算-6+(-6)=-12赋值给a,所以a的值为-12,也就是整个表达式的值,
12

#include <stdio.h>
int main()
{
    char c;
    int v0=0,v1=0,v2=0;
    do
    {
        switch(c=getchar())
        {
            case'a':case'A':
            case'e':case'E':
            case'i':case'I':
            case'o':case'O':
            case'u':case'U':v1 += 1;
            default:v0+= 1;v2+=1;
        }
    }while(c!='\n');
    printf("v0=%d,v1=%d,v2=%d\n",v0,v1,v2);
    return 0;
}

从键盘输入 ADescriptor<回车> ,则程序的运行结果是v0=12,v1=4,v2=12

代码switch语句中没有break,则每次找到入口进入后,顺序执行到代码块结束为止。例如当c为'A'时,从case 'A'进入,先后执行v1+=1;v0+=1;v2+=1;,而当c为'p'时,从default进入,先后执行v0+=1;v2+=1;,容易看出最终v0和v2是相等的

#include <stdio.h>
int main()
{
    char ch;
    while ((ch = getchar()) != '\n')
    {
        if (ch % 2 != 0 && (ch >= 'a' && ch <= 'z'))
        ch = ch - 'a' + 'A';
        putchar(ch);
    } 
    printf("\n");
    return 0;
}

输入1abcedf2df<回车> ,输出结果1AbCEdf2df

程序首先考虑ch的ASCII码值是不是奇数,再看是不是小写字母,同时满足时被改为大写字母

4.验证尼科彻斯定理

即:任何一个整数 m 的立方都可以写成 m 个连续奇数之和

1^3=1
2^3=3+5
3^3=7+9+11
4^3=13+15+17+19

#include <stdio.h>
int main()
{
    int m;
    while(~scanf("%d",&m))
    {
        int i,n=m*(m-1)+1;
        for(i=1;i<=m;i++)
        {
            printf("%d",n);
            n+=2;
            if(i!=m)
            {
                printf("+");
            }
        }
        printf("\n");
    }
}
#include "stdio.h"
#include "string.h"

int main()
{
    int m;  
    while (scanf("%d", &m) != EOF)
    {
        //long sum = m*m*m;
        int start = m*m - m + 1;;
        int i = 0;
        
        /*if (m%2 == 0)
        {
            start = m*m - m + 1;
        }
        else
        {
            start = m*m - 2*(m/2);
        }*/
        while (m > 1)
        {
            printf("%d+", start+2*i);
            i++;
            m--;
        }
        printf("%d\n", start+2*i);
    }
    
    return 0;
}

5.求等差数列前n项和

等差数列 2,5,8,11,14。。。。

#include <stdio.h>
int main(void)
{
	int num;
	while(scanf("%d", &num)!=EOF)
		printf("%d\n", ((4+3*(num-1))*num)>>1);
	return 0;
}

6.求平均数和负数的个数

首先输入要输入的整数个数n,然后输入n个整数。输出为n个整数中负数的个数,和所有正整数的平均值,结果保留一位小数。0即不是正整数,也不是负数,不计入计算

#include <stdio.h>

int main()
{
    int n;
    while(scanf("%d",&n) != EOF)
    {
        int cnt1 = 0;
        int cnt2 = 0;
        int sum = 0;
        int num;
        double result;
        for(int i = 0;i < n;i++)
        {
            scanf("%d",&num);
            if(num < 0)
            {
                cnt1++;
            }
            else if(num > 0)
            {
                sum += num;
                cnt2++;
            }
        }
        result =(float) sum / cnt2;
        printf("%d %0.1lf\n",cnt1,result);
    }   
    return 0;
}

7.旋转数组的最小数字

有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。

数据范围:1 \le n \le 100001≤n≤10000,数组中任意元素的值: 0 \le val \le 100000≤val≤10000

/**
 * 
 * @param rotateArray int整型一维数组 
 * @param rotateArrayLen int rotateArray数组长度
 * @return int整型
 */
int minNumberInRotateArray(int* rotateArray, int rotateArrayLen ) {
    // write code here
    if (0 == rotateArrayLen)
    {
        return 0;
    }
    
    int mid = 0, start = 0, end = 0;
    
    end = rotateArrayLen - 1;
    if (rotateArray[start] < rotateArray[end])
    {
        return rotateArray[start];
    }
    
    while (start < end)
    {
        mid = start + (end - start) / 2;
        if (rotateArray[mid] > rotateArray[end])
        {// 最小元素在右半侧
            start = mid + 1;
        }
        else if (rotateArray[mid] == rotateArray[end])
        {
            end = end - 1;
        }
        else
        {// 最小元素在左半侧
            end = mid;
        }
    }
    return rotateArray[start];
}
/**
 * 
 * @param rotateArray int整型一维数组 
 * @param rotateArrayLen int rotateArray数组长度
 * @return int整型
 */
int minNumberInRotateArray(int* rotateArray, int rotateArrayLen ) 
{
    int l = 0;
    int r = rotateArrayLen - 1;
    int middle;
    while (l < r) 
    {
        middle = (l + r) / 2;
        if (rotateArray[r] < rotateArray[middle]) 
        {
            l = middle + 1;
        } 
        else if (rotateArray[r] > rotateArray[middle]) 
        {
            r = middle;
        } 
        else 
        {
            r--;
        }
    }
    return rotateArray[l];
}

8.对数组a进行插入排序(升序)

int a[] = {4, 0, 2, 3, 1}, i, j, t;
for(i = 1;i < 5;i++)
{
    t = a[i];
    j = i - 1;
    while(j >= 0 && t < a[j])
    {
        a[j + 1] = a[j];
        --j;
    } 
    a[j + 1] = t;
}

这是一个升序插入排序算法,读完即懂,第i次排序时,t=a[i]作为临时变量保存这一次待插入值,j=i-1故而while循环中j是从下标i的前一项开始向下标0遍历,判断t<a[j]为真a[j+1]=a[j],j+1在遍历之初是等于i的,也就是将下标i位置用前边较大的值覆盖,依次把前边的元素后移,直到a[j]不大于t的时候将t插入到下标j+1位置,使得前i个元素达到有序,方便第i+1次排序操作,所以第i次排序时前边i-1个元素都是有序的。

9.找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回

集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且有一个数字重复 。

给定一个数组 nums 代表了集合 S 发生错误后的结果。

int* findErrorNums(int* nums, int numsSize, int* returnSize)
{
    int* a = (int*)malloc(sizeof(int)*(numsSize));
    for(int i = 0; i < numsSize; i++)
    {   // 初始化数组
        a[i] = 0;
    }
    for(int i = 0; i < numsSize; i++)
    {   // 关键:记录各个数字出现的频次
        a[nums[i]-1]++;
    }
    int* res = (int*)malloc(sizeof(int)*2);
    for(int i = 0; i < numsSize; i++)
    {
        if(a[i] == 2)
        {
            res[0] = i+1;
        }
        if(a[i] == 0)
        {
            res[1] = i+1;
        }
    }
    *returnSize = 2;
    return res;
}
int* findErrorNums(int* nums, int numsSize, int* returnSize)
{
    *returnSize = 2;
    //遍历nums数组,将其中数据对应的位置1, 哪一位如果已经重置过则意味着数据重复了
    int *arr = (int *)calloc(numsSize + 1, sizeof(int));//申请numsSize个整形空间,并初始化为0
    int *ret = (int *)calloc(*returnSize, sizeof(int)); //申请2个整形空间,并初始化为0
    int cur_sum = 0, old_sum = 0;
    for (int i = 0; i < numsSize; i++) 
    {
        if (arr[nums[i]] == 1) 
        {   //这个数字在上边数组的对应位置已经置过1了,则重复。
            ret[0] = nums[i];//找到重复的数字
        } 
        arr[nums[i]] = 1;   //将标记数组的对应数据位置1
        old_sum += i + 1;   // 1~n的求和
        cur_sum += nums[i]; //当前数组中的数据求和(多了一个重复的,少了一个丢失的)
    } 
    ret[1] = old_sum - (cur_sum - ret[0]);//原始总和,减去去掉重复后的当前总和就是丢失的数字
    free(arr);
    return ret;
}

10.密码检查

小明同学最近开发了一个网站,在用户注册账户的时候,需要设置账户的密码,为了加强账户的安全性,小明对密码强度有一定要求:

1. 密码只能由大写字母,小写字母,数字构成;

2. 密码不能以数字开头;

3. 密码中至少出现大写字母,小写字母和数字这三种字符类型中的两种;

4. 密码长度至少为8

现在小明受到了n个密码,他想请你写程序判断这些密码中哪些是合适的,哪些是不合法的。

输入描述:

输入一个数n,接下来有n(n≤100)行,每行一个字符串,表示一个密码,输入保证字符串中只出现大写字母,小写字母和数字,字符串长度不超过100。

输出描述:

输入n行,如果密码合法,输出YES,不合法输出NO

#include<stdio.h>
#include<ctype.h>
#include<string.h>
int main(void)
{
    int n,count=0;
    char s[100];
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        int count1 = 0, count2 = 0, count3 = 0;
        scanf("%s", &s);
        if (strlen(s) < 8)
        {
            printf("NO\n");
            continue;
        }
        if (isdigit(s[0]) != 0)
        {
            printf("NO\n");
            continue;
        }
        int j = 0;
        while (s[j] != '\0')
        {
            if (isupper(s[j]) != 0)
                count1 = 4;
            else if (islower(s[j]) != 0)
                count2 = 2;
            else if (isdigit(s[j]) != 0)
                count3 = 1;
            else
            {
                count1 = 0, count2 = 0, count3 = 0;
                break;
            }
            j++;
        }
        count = count1 + count2 + count3;
        if (count == 7 || count == 3 || count == 5 || count == 6)
            printf("YES\n");
        else
            printf("NO\n");
    }
}
#include<stdio.h>
#include<ctype.h>
#include<string.h>
int main(void)
{
	int n,count=0;
	char s[100];
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		int count1 = 0, count2 = 0, count3 = 0;
		scanf("%s", &s);
		if (strlen(s) < 8)
		{
			printf("NO\n");
			continue;
		}
		if (isdigit(s[0]) != 0)
		{
			printf("NO\n");
			continue;
		}
		int j = 0;
		while (s[j] != '\0')
		{
			if (isupper(s[j]) != 0)
				count1 = 4;
			else if (islower(s[j]) != 0)
				count2 = 2;
			else if (isdigit(s[j]) != 0)
				count3 = 1;
			else
			{
				count1 = 0, count2 = 0, count3 = 0;
				break;
			}
			j++;
		}
		count = count1 + count2 + count3;
		if (count == 7 || count == 3 || count == 5 || count == 6)
			printf("YES\n");
		else
			printf("NO\n");
	}
}

11.将字符数组ch中的大写字母转换成小写

#include <stdio.h>
int main()
{
    char ch[80] = "123abcdEFG*&";
    int j;
    puts(ch);
    for(j = 0; ch[j] != '\0'; j++)
        if(ch[j] >= 'A' && ch[j] <= 'Z')
            ch[j] = ch[j] + 'e' - 'E';
    puts(ch);
    return 0;
}

12.数字在升序数组中出现的次数

给定一个长度为 n 的非降序数组和一个非负数整数 k ,要求统计 k 在数组中出现的次数。

数据范围:0 \le n \le 1000 , 0 \le k \le 1000≤n≤1000,0≤k≤100,数组中每个元素的值满足 0 \le val \le 1000≤val≤100

/**
 * 
 * @param data int整型一维数组 
 * @param dataLen int data数组长度
 * @param k int整型 
 * @return int整型
 */
int GetNumberOfK(int* data, int dataLen, int k ) 
{
    // write code here
    //这种有序还是数组就要用二分法,比直接遍历能节省一半时间
    if(dataLen==0)return 0;
    int i,j,right=0,left=0,m;
    i=0;
    j=dataLen-1;
    while(i<=j)
    {
        m=(i+j)/2;
        if(k>=data[m])
            i=m+1;
        else
            j=m-1;
    }
    right=i;//i,j需要重新赋值!因为需要再来一次二次查找
    i=0;
    j=dataLen-1;
    while(i<=j)
    {
        m=(i+j)/2;
        if(k>data[m])
            i=m+1;
        else
            j=m-1;
    }
    left=j;
    return right-left-1;
}
/**
 * 
 * @param data int整型一维数组 
 * @param dataLen int data数组长度
 * @param k int整型 
 * @return int整型
 */
int GetNumberOfK(int* data, int dataLen, int k ) 
{
    int i=0;
    int ret=0;
    for(i=0;i<dataLen;i++)
    {
        if(data[i]==k)
        {
            ret++;
        }
    }
    return ret;// write code here
}

采用遍历也能搞定,不过数组为非降序,采用二分查找的思想最优,先二分找到最左边的数字位置,再二分查找最右边的数字位置,两个位置相减+1就是长度了
中间比找的值大:则要找的数字肯定在右边, left = mid + 1;
中间比找的值小:则要找的数字肯定在左边, right = mid - 1;
中间值与找的值相同:
找的最左边数字:如果mid就是left,则返回mid就行,否则重置right=mid-1,把中心不断向左偏移
找的最右边数字:如果mid就是right,则返回mid就行,否则重置left=mid+1,把中心不断向右偏移
 

int get_last_or_first_idx(int *data, int len, int k, int flag) 
{    //flag:0-找左边, 1-找右边
    int left = 0, right = len - 1, mid;
    while(left <= right) 
    {
        mid = left + (right - left) / 2;
        if (data[mid] > k)
            right = mid - 1;
        else if (data[mid] < k)
            left = mid + 1;
        else 
        {
            if(flag == 0) 
            {   //flag==0时,找最左边的数字
                if(mid == left || data[mid-1] != k) 
                    return mid;
                else right = mid - 1;    //把中心向左推
            }
            else 
            {   //flag==1时,找最右边的数字
                if (mid == right || data[mid+1] != k) 
                    return mid;
                else left = mid + 1;//把中心向右推
            }
        }
    } 
    return -1;
} 

int GetNumberOfK(int* data, int dataLen, int k ) 
{
    if (dataLen == 0) 
        return 0;
    int left = get_last_or_first_idx(data, dataLen, k, 0);
    int right = get_last_or_first_idx(data, dataLen, k, 1);
    if (left == -1 && right == -1) 
        return 0; //表示没有找到k这个数据
    return right - left + 1;
}

13.整数转换

编写一个函数,确定需要改变几个位才能将整数A转成整数B

输入:A = 29 (或者0b11101), B = 15(或者0b01111) 输出:2

其实问需要修改多少个比特位,问的就是有多少个比特位不同而已,因为有多少位不同就修改多少位。

int convertInteger(int A, int B)
{
    A^=B;
    int ret=0;
    for(int i=0;i<32;i++)
    {
        if((A>>i)&1==1)
        {
            ret++;
        }
    }
    return ret;
}
int get_bin_count(int num) 
{
    int count = 0;
    for (int i = 0; i < 32; i++) 
    {
        if ((num >> i) & 1)
            count++;
    } 
    return count;
} 

int convertInteger(int A, int B)
{
    return get_bin_count(A^B);
}

14.至少是其他数字两倍的最大数

给你一个整数数组nums,其中总是存在唯一的一个最大整数 。请你找出数组中的最大元素并检查它是否 至少是数组中每个其他数字的两倍 。如果是,则返回 最大元素的下标 ,否则返回 -1 。

示例:
输入:nums = [3,6,1,0]
输出:1
解释:6 是最大的整数,对于数组中的其他整数,6 大于数组中其他元素的两倍。6 的下标是 1 ,所以返回 1 。

输入:nums = [1,2,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值