20级青藤工作室第三次考核参考答案

在这里插入图片描述
岁月,对人来说,是一样人捉摸不到的东西。然而,就是这样东西,使人更珍惜自己的时光。如果,岁月可以给每一个人愿望。我希望,岁月可以倒转。

20级青藤工作室第三次考核参考答案

第一题

题目

一、证明哥德巴赫猜想
哥德巴赫猜想:任一大于 2 的偶数都可写成两个素数之和。
请涉及一个程序,输入一个不小于 2 的 int 型的偶数 n,输出两个相加和为 n 的素数。
示例一:
输入: 20
输出: 20=13+7
示例二:
输入: 98
输出: 98=19+79

源码:

#include<stdio.h>
#include<math.h>
int isPrime(int n)
{
	if (n == 1 || (n % 2 == 0 && n != 2))
		return 0;
	else
	{
		int m = sqrt(n);
		for (int i = 2; i <= m; i++)
		{
			if (n % i == 0)
				return 0;
		}
	}
	return 1;
}
void main()
{
	int n;
	printf("请输入一个大于2的偶数: ");
	scanf("%d", &n);
	for (int i = 2; i <= n / 2; i++)
	{
		if (isPrime(i) && isPrime(n - i))
		{
			printf("%d=%d+%d", n, i, n - i);
			return;
		}
	}
}

第二题

题目

二、输入一个长度为 n 的整型数组 arr ,输出 arr 的一个最长单调递增子序列的长度
单调递增子序列:不该变原来数组顺序,从数组中抽出来的数按原来顺序排列,是从小到大
例如:
原数组:[14, 25, 16, 14, 47, 48, 5, 14]
单调递增子序列:[14, 16, 47, 48], [25, 47, 48], [16, 47, 48], [14, 47, 48], …
输入:
第一行输入:n 的大小
第二行输入:n 个整数
输出:
该数组的最长单调递增子序列的长度
例子:
输入:8
输入:[1 ,5 ,3, 8, 10, 6, 4, 9]
输出:4

源码

/**
 * 
 * 输入一个长度为 n 的数组 arr ,输出 arr 的一个最长单调递增子序列的长度
 * 单调递增子序列:不该变原来数组顺序,从数组中抽出来的数按原来顺序排列,是从小到大
 * 例如:
 * 原数组:[14, 25, 16, 14, 47, 48, 5, 14]
 * 单调递增子序列:[14, 16, 47, 48], [25, 47, 48], [16, 47, 48], [14, 47, 48], ...
 * 
 * 输入: 
 * 第一行输入:n 的大小
 * 第二行输入:n 个整数
 * 输出:
 * 该数组的最长单调递增子序列的长度
 * 
 * 例子:
 * 输入:
 * 8
 * 1 5 3 8 10 6 4 9
 * 输出:
 * 4
 * 
 */

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int n = 0, maxLen = 0;
    // 输入数组长度 n
    scanf("%d", &n);
    // 定义两个长度为 n 的 int 数组
    // arr 用于储存输入的 n 个整数
    int *arr = (int *)malloc(sizeof(int)*n);
    // dp 用于保存以当前数为最后一位的最长单调递增子序列的长度
    // dp[i] 表示在数组 arr 中以 arr[i] 为最后一位的最长单调递增子序列的长度
    int *dp = (int *)malloc(sizeof(int)*n);
    
    // 输入数字存入 arr
    for (int  i = 0; i < n; i++) {
        scanf("%d", arr+i);
    }
    // 以第一个数为最后一位的最长单调递增子序列的长度为 1 
    // 注意:下标 0 代表第一个数
    dp[0]=1;
    /**
     * 从第一位之后,arr[i] 的 dp[i] 的值为在 0 ~ i-1 中比自己小的数 arr[j] 的 dp[j] + 1 
     * 且找到的 dp[j] + 1 大于 dp[i](dp[i] 的初始值为 1)
    */
    for(int i = 1; i < n; i++) {
        dp[i] = 1;
        for(int j = 0; j < i; j++) {
            if(arr[i] > arr[j]) {
                dp[i] = dp[i] > dp[j]+1 ? dp[i] : dp[j]+1;
            }
        }
    }
    // 输出数组 dp 中最大的数,就是最长单调递增子序列的长度
    for(int i = 0; i < n; i++) {
        if(maxLen < dp[i]) {
            maxLen = dp[i];
        }
    }
    printf("%d\n", maxLen);

    return 0;
}

第二种思路

#include<stdio.h>

int longestIncreasingSubsequence(int nums[], int len) {
	//直接初始化最长递增子序列长度为1
	int max_len = 1;
	//用于保存比较过的起始值中的最小值
	int min;
	for (int i = 0; i < len; i++) {
		//先用cur保存本次比较的起点的值
		int cur = nums[i];
		//保存本次比较的递增子序列长度
		int cur_len = 1;
		//当某次比较的长度小于等于max_len则无需继续比较,直接返回max_len
		if (len - i <= max_len)
			return max_len;
		//当某次比较的起点的值大于该值则可以直接跳过本次循环
		//因为起点值本身大于min,而本次比较的长度还小于起点为min是比较的长度
		//那么得出的结果一定不大于max_len
		if (i != 0 && cur >= min)
			continue;
		//运行到这里说明cur<min
		min = cur;
		for (int j = i + 1; j < len; j++) {
			if (nums[j] > cur) {
				cur = nums[j];
				cur_len++;
			}
		}
		//如果本次比较得出的结果大于max_len就将结果赋值给max_len
		if (cur_len > max_len)
			max_len = cur_len;
	}
	return max_len;
}
int main() {
	int nums[] = { 4,5,2,8,10,6,4,9,11 };
	int len = 9;
	int res = longestIncreasingSubsequence(nums, len);
	printf("最长递增子序列长度为:%d", res);
	return 0;
}


第三题

题目

三、现有一个 n 级台阶,一只青蛙一次只能跳一阶或者两阶或者三阶,求该青蛙跳完这 n
级阶梯共有多少种方法,即请编写一个程序,输入 n (n>0),输出方法总数。

源码

#include<stdio.h>

int jump(int n)
{
	if (n <= 2)
		return n;
	else if (n == 3)
		return 4;
	else
		return jump(n - 1) + jump(n - 2) + jump(n - 3);
}
int main()
{
	printf("请输入台阶数(>0):");
	int n;
	scanf("%d", &n);
	printf("总共有%d种方法\n", jump(n));
	return 0;
}

第四题

题目

四、给定一个二维网格和一个单词,找出该单词是否存在于网格中。单词必须按照字母顺序,
通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。
同一个单元格内的字母不允许被重复使用。
举例:
board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]
给定 word = “ABCCED”, 返回 true
给定 word = “SEE”, 返回 true
给定 word = “ABCB”, 返回 false

源码

//1,将该题分解为:给定坐标[i,j],在二维网格中是否能够匹配单词,在二维网格中所有匹配第一个字母的位置匹配一次单词
//2,如何在二维网格中匹配一个单词,回溯法

//回溯法匹配单词 0代表失败,1代表成功
int backTrackExist(char** board, int iRowSize, int iColSize, int iRow, int iCol, char* word, char** pBFlag, int iStep)
{
    int     bMatch = 0;//默认为假
    int     iWordLen = strlen(word);

    //1,结束条件
    if (iStep == iWordLen - 1)
    {
        return 1;
    }

    //2,判定下一步是否有匹配单词
    pBFlag[iRow][iCol] = 1;
    if ((iRow - 1 >= 0) && (pBFlag[iRow - 1][iCol] == 0) && (board[iRow - 1][iCol] == word[iStep + 1]))
    {
        //上匹配
        bMatch = backTrackExist(board, iRowSize, iColSize, iRow - 1, iCol, word, pBFlag, iStep + 1);
        if (bMatch) return bMatch;
    }
    if ((iCol + 1 < iColSize) && (pBFlag[iRow][iCol + 1] == 0) && (board[iRow][iCol + 1] == word[iStep + 1]))
    {
        //右匹配
        bMatch = backTrackExist(board, iRowSize, iColSize, iRow, iCol + 1, word, pBFlag, iStep + 1);
        if (bMatch) return bMatch;
    }
    if ((iRow + 1 < iRowSize) && (pBFlag[iRow + 1][iCol] == 0) && (board[iRow + 1][iCol] == word[iStep + 1]))
    {
        //下匹配
        bMatch = backTrackExist(board, iRowSize, iColSize, iRow + 1, iCol, word, pBFlag, iStep + 1);
        if (bMatch) return bMatch;
    }
    if ((iCol - 1 >= 0) && (pBFlag[iRow][iCol - 1] == 0) && (board[iRow][iCol - 1] == word[iStep + 1]))
    {
        //左匹配
        bMatch = backTrackExist(board, iRowSize, iColSize, iRow, iCol - 1, word, pBFlag, iStep + 1);
        if (bMatch) return bMatch;
    }

    //3,回溯处理
    pBFlag[iRow][iCol] = 0;
    return 0;
}

int exist(char** board, int boardSize, int* boardColSize, char* word) {
    int     i = 0;
    int     j = 0;
    int     k = 0;
    int     iRow = boardSize;
    int     iCol = boardColSize[0];
    int     bRet = 0;//默认为假
    char** pBoardFlag = NULL;

    if ((NULL == board) || (NULL == word)) return 0;

    //1,初始化二维网格匹配标记数组
    pBoardFlag = (char**)malloc(sizeof(char*) * iRow);
    for (i = 0; i < iRow; i++)
    {
        pBoardFlag[i] = (char*)malloc(sizeof(char) * iCol);
    }

    //2,循环二维网格,寻找坐标,进行匹配单词
    for (i = 0; i < iRow; i++)
    {
        for (j = 0; j < iCol; j++)
        {
            if (board[i][j] == word[0])
            {
                for (k = 0; k < iRow; k++)
                {
                    memset(pBoardFlag[k], 0x00, sizeof(char) * iCol);
                }

                //3,给定坐标[i,j],匹配单词
                bRet = backTrackExist(board, iRow, iCol, i, j, word, pBoardFlag, 0);
                if (bRet) return bRet;
            }
        }
    }

    //4,释放空间
    for (k = 0; k < iRow; k++)
    {
        free(pBoardFlag[k]);
    }
    free(pBoardFlag);

    return bRet;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值