数组题目合集

一.计算一个3*3的整形矩阵对角线元素之和(二维数组)

1.一开始就设好的

#include <stdio.h>
int main()
{
	int arr[3][3]={{1,2,3},{4,5,6},{7,8,9}};//自己设出来的矩阵
	int sum=0;
	int i=0;//要先声明变量 
	
	for(i=0;i<3;i++)
	{//注意括号 
	
		
	sum +=arr[i][i];//注意是arr[i][i],不是[i][i],这里是一个索引值 
	
    }  printf("%d\n",sum);	//如果放在循环里面就会产生每次计算的值1 6 15 ,循环外只会打印15 
     return 0;

2需要输入的

#include <stdio.h>

int main() {
    int arr[3][3];
    int sum = 0;
    int i, j;

    // 提示用户输入完整的3x3矩阵
    printf("请输入一个3x3矩阵的元素:\n");
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            scanf("%d", &arr[i][j]); // 读取用户输入的矩阵元素
        }
    }//注意这里有两个循环,因为是二维数组

    // 下面这个循环用来计算对角线元素的和
    for (i = 0; i < 3; i++) {
        sum += arr[i][i]; // 累加对角线元素
    }

    // 打印对角线元素的和
    printf("对角线元素之和为: %d\n", sum);

    return 0;
}

 注意:如果你上面不写两个循环,只用下面的话,你输入矩阵的值他只会选前三个当作对角线的值

二排序问题

1.找出n个数字中最大最小并输出

#include <stdio.h>

int main() {
    int n, arr[10000];
    
    scanf("%d", &n); // 读取数组元素的数量

    // 读取数组的第一个元素,并初始化max和min
    scanf("%d", &arr[0]);
    int max = arr[0];
    int min = arr[0];

    for (int i = 0; i < n; i++) { 
        scanf("%d", &arr[i]); // 读取数组的下一个元素
        if (arr[i] < min) {
            min = arr[i]; // 更新最小值
        }
        if (arr[i] > max) {
            max = arr[i]; // 更新最大值
        }
    }
    
    // 打印数组的所有元素
    for (i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    // 打印最大值和最小值
    printf("Max: %d\n", max);
    printf("Min: %d\n", min);

    return 0;
}

2.给n个数对这些数排序

#include <stdio.h>
int main() {
    int n, arr[1000];
    scanf("%d", &n);
//读取用户输入的 n 个整数,并将它们存储在数组 arr 中。
//循环从索引 0 开始,一直到 n-1(因为数组索引是从 0 开始的)。
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }
    int min_idx = 0; // 假设第一个元素是最小的
    for (int i = 1; i < n; i++) { // 从第二个元素开始寻找最小值
        if (arr[i] < arr[min_idx]) {
            min_idx = i; // 更新最小值的索引
        }
    }
    // 交换第一个元素和找到的最小值
    int temp = arr[0];
    arr[0] = arr[min_idx];
    arr[min_idx] = temp;
    
    // 打印数组
    for (int i = 0; i < n; i++) {
        printf("%d\n", arr[i]);
    }
    return 0;
}

3. 二分查找(在 有序!数组中查找某个数)

计算中间元素下标,左右下标----->中间元素下标

​
#include <stdio.h>

int main() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
    int sz = sizeof(arr) / sizeof(arr[0]) - 1; // 计算数组 arr 的最后一个元素的索引
    int left = 0;
    int right = sz;//不用减一
//因为我们在计算 mid 时已经通过 mid = left + (right - left) / 2 避免了下标越界的问题。
    int key = 7; // 要找的元素是7
    int mid;
    int find = 0; // 假设开始没有找到

    while (left <= right) {
        mid = left + (right - left) / 2;
 // 避免溢出!
//如果写成mid = (left+right)/2;有溢出风险且上面right需要减一;
        if (arr[mid] < key) {
            left = mid + 1;
        } else if (arr[mid] > key) {
            right = mid - 1;
        } else {
            find = 1; // 找到了
            break;
        }
    }

    if (find) {//非零为真
        printf("找到了,下标为%d", mid);
    } else {
        printf("没找到\n");
    }

    return 0;
}

​

4.给一串数字以0结束,倒着输出 但不输出0

#include <stdio.h>

int main() {
	int arr[1000]; // 假设最多读取1000个整数
	int i = 0; // 数组索引
	int n;
	
	// 读取一行内以空格分隔的整数,直到遇到00
	while (1) {
		scanf("%d", &n);
		if (n == 0) break; // 如果输入0,则结束输入
		arr[i++] = n; // 将读取的整数存储到数组中
	}
	
	// 反向打印这一串整数

	for (int j = i - 1; j >= 0; j--) {
		printf("%d ", arr[j]);
	}
	printf("\n");
	
	return 0;
}

 5.冒泡排序

#include <stdio.h>
int main()
{
	int arr[10]={10,9,8,7,6,5,4,3,2,1};
	for(int i=0;i<9;i++)
	{
///外层 for 循环控制排序的轮数,因为数组有10个元素,所以需要进行9轮比较才能完成排序
		for(int j=0;j<10-1-i;j++)
//内层 for 循环用于在每轮排序中比较相邻的元素。
//10-1-i 表示每轮排序中,比较的次数会随着排序的进行而减少,因为数组后面的元素已经排好序了。
		{
			if(arr[j]>arr[j+1])
//如果当前元素 arr[j] 大于它后面的元素 arr[j+1],则进入 if 语句块。
			{
//交换两个元素的位置,使得较小的元素移到数组的前面,较大的元素排在后面。
				int t=arr[j+1];
				arr[j+1]=arr[j];
				arr[j]=t;
			}
		}
	
	}
	for(int i=0;i<10;i++)
	{
		printf("%d ",arr[i]);
	}
	return 0;//如果要打印一堆数组,则要重新写一个for循环
}

三.计算数列之和

计算 1+2+3+⋯+(𝑛−1)+𝑛1+2+3+⋯+(n−1)+n 的值 ,输入n,输出和的值

#include <stdio.h>

int main() {
    int arr[1000];
    int n;
    int sum = 0; // 初始化累加和为0

    // 读取用户输入的n值
    scanf("%d", &n);

    // 检查n是否小于等于数组的长度1000
    if (n <= 0 || n > 1000) {
        printf("输入的数字不满足条件,应为1至1000之间的整数。\n");
        return 1;
    }

    // 初始化数组并计算累加和
    for (int i = 0; i < n; i++) {
        arr[i] = i + 1; // 将数组的每个元素设置为1到n,
//注意:
1.数组元素初始化:代码试图将每个数组元素 arr[i] 设置为 n 的值,但这不是求和的目的。如果我们想要计算从 1 到 n 的和,我们应该将每个数组元素初始化为它自己的索引值 i。
2.求和逻辑:累加和 sum 应该基于数组元素的实际值进行累加,而不是简单地将 n 重复相加。
        sum += arr[i];   // 累加和加上当前元素的值
    }

    // 打印最终的和
    printf("%d\n", sum);//放循环外面是因为输出一个值

    return 0;
}

关于printf什么时候放外面什么时候放里面问题

在C语言中,`printf` 函数用于输出数据到标准输出设备,通常是你的显示器或终端窗口。`printf` 的使用位置取决于你想要实现的程序逻辑和输出格式。以下是一些常见的使用场景:

1. **循环外部**:当你想要在循环执行完毕后输出最终结果时,将 `printf` 放在循环外部。

int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += i;
    }
    printf("Sum is: %d\n", sum); // 循环结束后打印总和
    ```

2. **循环内部**:如果你需要在每次循环迭代时都打印信息,将 `printf` 放在循环内部

  for (int i = 0; i < n; i++) {
        printf("Value of i: %d\n", i); // 每次迭代都打印当前的 i 值
    }
    ```

3. **条件语句中**:当输出依赖于某些条件是否满足时,可以将 `printf` 放在 `if` 或 `else` 语句块中。
 

  if (condition) {
        printf("Condition is met.\n");
    } else {
        printf("Condition is not met.\n");
    }

4. **函数调用后**:在调用一个函数并希望立即显示返回结果时,可以将 `printf` 放在函数调用后。
   

 int result = someFunction();
    printf("Result of function: %d\n", result);
    ```

5. **程序开始和结束**:通常在 `main` 函数的开始处打印欢迎信息,在程序结束前打印结束信息或最终结果。
   

 printf("Program starts.\n");
    // ... 程序代码 ...
    printf("Program ends.\n");
    ```

6. **错误处理**:在检测到错误时,`printf` 用于输出错误信息。
 

  if (errorCondition) {
        printf("Error: Something went wrong!\n");
        return 1; // 非零值通常表示程序出错
    }

7. **格式化输出**:当需要格式化输出数据,如对齐、指定小数点后位数等,`printf` 可以与格式化输出一同使用
 

   printf("Name: %s, Age: %d\n", name, age);
    ```

四. 矩阵转置(二维数组)

#include <stdio.h>

int main() {
    int matrix[3][4];
    int i, j;
    // 填充矩阵
    for(i = 0; i < 3; i++) {
        for(j = 0; j < 4; j++) {
            scanf("%d", &matrix[i][j]);
        }
    }
    // 交换矩阵的行和列
    for(i = 0; i < 3; i++) {
        for(j = 0; j < i; j++) { // 注意这里 j < i,避免交换对角线上的元素和自己
            // 交换 matrix[i][j] 和 matrix[j][i]
            int temp = matrix[i][j];
            matrix[i][j] = matrix[j][i];
            matrix[j][i] = temp;
        }
    }
    // 打印修改后的矩阵
    for(i = 0; i < 3; i++) {
        for(j = 0; j < 4; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
    return 0;
}

五.冰雹猜想 

给出一个正整数 𝑛n,然后对这个数字一直进行下面的操作:如果这个数字是奇数,那么将其乘 33 再加 11,否则除以 22。经过若干次循环后,最终都会回到 11。经过验证很大的数字(7×10117×1011)都可以按照这样的方式比变成 11,所以被称为“冰雹猜想”。例如当 𝑛n 是 2020,变化的过程是 20→10→5→16→8→4→2→120→10→5→16→8→4→2→1。

#include <stdio.h>

int main() {
    int arr[1000];
    int i = 0; // 初始化数组索引
    int n;
    scanf("%d", &n);

    while (n != 1) { // 循环直到n变为1
        arr[i++] = n; // 存储当前的n值,并增加索引
        if (n % 2 == 0) {
            n = n / 2; // 如果n是偶数,除以2
        } else {
            n = n * 3 + 1; // 如果n是奇数,乘以3再加1
        }
    }
    arr[i++] = n; // 将1加入数组,把n赋值给arr[i]自增,本来是零然后加一,变成1,在循环外
//或者printf("1 ");也可以,注意有空格

    // 反向打印数组
    for (int j = i - 1; j >= 0; j--) {
        printf("%d ",arr[j]);//这里有空格别忘了,在引号里面
        //这个下面的不写也行
         if (j > 0) { // 除了最后一个数字外,每个数字后加空格
            printf(" ");
        }
    }
    printf("\n"); // 打印换行符

    return 0;
}

 六杨辉三角

给出 𝑛(𝑛≤20),输出杨辉三角的前 𝑛 行。

#include <stdio.h>
int main()
{
	int n,matrix[100][100]={0};//每行最多有20个数字,注意要初始化
     scanf("%d",&n);
	matrix[1][1]=1;
//初始化杨辉三角的顶部元素为1,所以下面的i就从2开始而不是零注意变通
	for(int i=2;i<=n;i++){
//这个循环用于生成杨辉三角的第2行到第 n 行。这里使用 <= n 是正确的,因为我们需要包含第 n 行。
	        for(int j=1;j<=i;j++){
//内层循环用于生成每一行的元素。j <= i 是正确的,因为第 i 行有 i 个元素,包括两端的1
		matrix[i][j]=matrix[i-1][j-1]+matrix[i-1][j];		
			}
	}
//这两个嵌套的 for 循环用于计算杨辉三角的每一行和每一列的值。外层循环 i 从2遍历到 n,表示杨辉三角的第2行到第 n 行。内层循环 j 从1遍历到 i,表示每一行的第1个到第 i 个元素。matrix[i][j] 的值是其正上方两个数的和,即 matrix[i - 1][j - 1] 和 matrix[i - 1][j]。
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i;j++){//注意j初始值即循环条件
			printf("%d ",matrix[i][j]);
		}//注意要有大括号
		printf("\n");//注意这个在小循环外
	}
//这两个嵌套的 for 循环用于打印杨辉三角。外层循环 i 同样从1遍历到 n,内层循环 j 从1遍历到 i。printf 函数用于打印 matrix[i][j] 的值,并且每个数字后面有一个空格。每打印完一行后,使用 printf("\n"); 换行。
	return 0;
}

七.涉及字符串

1.输入一行,一个字符串

输出一个字符串,即将原字符串中的所有小写字母转化为大写字母。

#include <stdio.h>
int main()
{
	char str[127];//声明一个字符数组,为啥是127?
	//选择127是因为在ASCII编码中,最大值是127,
	//这样可以确保数组能够存储一个完整的ASCII字符集,包括所有小写字母和大写字母。
	scanf("%s",str);//为什么没有&?数组名作为指针
	char *p=str;
	while(*p!='\0'){
		//这个 while 循环会一直执行,直到遇到字符串的结束标志 '\0'
		if('a'<=*p&&*p<='z'){
	//'a' <= *p:这个条件检查 p 指向的字符是否大于或等于字符 'a'。在ASCII码表中,小写字母从 'a' (ASCII码 97) 开始。
   //	*p <= 'z':这个条件检查 p 指向的字符是否小于或等于字符 'z'。在ASCII码表中,小写字母在 'z' (ASCII码 122) 结束。
			printf("%c",*p-'a'+'A');
		}
		else 
		{	printf("%c",*p);
		
	}
	p++;//在循环的每次迭代结束时,指针 p 会增加,移动到下一个字符
	}
	return 0;
  }

 2.蒟蒻虽然忘记密码,但他还记得密码是由一个字符串组成。密码是由原文字符串(由不超过 50 个小写字母组成)中每个字母向后移动 n 位形成的。z 的下一个字母是 a,如此循环。他现在找到了移动前的原文字符串及 n,请你求出密码。

Input

第一行:n。第二行:未移动前的一串字母。

Output

第一行,是此蒟蒻的密码。

错误代码:

#include <stdio.h>
int main()
{
	char str[127];//为什么这里也是127,写更大一点可以吗
	scanf("%s",str);
	char *p=str;
	int n;
	scanf("%d",&n);

	while(*p!='\0'){
		int c=*p+n;
		if(c>'z')
		{	c-=26;
			printf("%c",c);
			p++;}
			
		
	}
		return 0;
	}
	

 错误原因:

1.先输入n,后输入字符不符合要求

2.if括号那里有问题

正确代码:

#include <stdio.h>
int main()
{
	char str[127];//为什么这里也是127,写更大一点可以吗
	
	char *p=str;
	int n;
	scanf("%d",&n);
	scanf("%s",str);

	while(*p!='\0'){
		int c=*p+n;
		if(c>'z')
			c-=26;
			printf("%c",c);//if这里不加括号表示if只执行c-=26;
/*也可以写成 if(c>'z')
        {    c-=26;
            printf("%c",c);
            }
            
        else{
            printf("%c",c);
        } 
        p++;注意p++在if外
    }*/
		
			p++;}
		
	
	return 0;
}

<think>好的,用户想了解C++中的标记数组题目。首先,我需要确定用户的基础,可能是个刚开始学习算法的人,或者正在准备编程面试。标记数组通常用于处理需要记录状态的问题,比如查找重复元素、统计出现次数等。 接下来,我应该解释什么是标记数组。用简单的例子说明,比如一个布尔数组,用来标记某个元素是否出现过。然后,举几个常见的应用场景,比如判断数组是否有重复元素、统计素数、矩阵中的特定路径问题等。 需要确保例子具体且易于理解。例如,判断重复元素时,可以用一个数组来记录每个数字是否被访问过。统计素数可以用埃拉托斯特尼筛法,这也是标记数组的应用。矩阵中的问题,比如岛屿数量,可以用二维标记数组记录访问过的位置。 还要注意代码的正确性,比如在C++中数组的大小可能需要根据问题调整,或者使用更灵活的结构如vector。同时提醒用户注意可能的越界问题,或者空间复杂度的问题,如果数据范围很大,可能需要优化,比如使用位运算代替数组。 用户可能想知道如何选择使用标记数组,或者在不同问题中的变体。比如有时可以用原地算法,用输入数组本身作为标记,节省空间。这时候需要给出例子,比如将访问过的位置设为特定值,如-1或0。 还要考虑常见错误,比如忘记初始化标记数组,或者在回溯时没有正确恢复状态,导致结果错误。这时候需要强调初始化和状态管理的重要性。 最后,总结标记数组的优缺点,适用场景,以及可能的替代方法,比如哈希表在某些情况下可以替代标记数组,但可能有不同的时间空间复杂度。 现在需要把这些思路组织成结构清晰的回答,分步骤说明,并给出代码示例,确保语法正确,用中文解释清楚。</think>在C++算法题目中,标记数组是一种通过辅助空间记录状态信息的常用技巧。以下是分步骤详解: 一、核心概念 标记数组本质是一个辅助数组,通常用bool或int类型实现,用于记录原数组中元素的状态。典型应用场景包括: 1. 元素是否被访问过 2. 元素是否满足特定条件 3. 动态规划中的状态标记 二、典型应用场景及代码示例 1. 查找重复元素(LeetCode 217) 问题:判断数组中是否存在重复元素 解法:用标记数组记录元素出现次数 $$nums = [1,2,3,1]$$ ```cpp bool containsDuplicate(vector<int>& nums) { // 假设数据范围在0-10^4之间 bool flag[10001] = {false}; for(int num : nums) { if(flag[num]) return true; flag[num] = true; } return false; } ``` 2. 素数筛选(埃拉托斯特尼筛法) 问题:找出小于n的所有素数 ```cpp vector<int> countPrimes(int n) { vector<bool> isPrime(n, true); for(int i=2; i*i<n; ++i) { if(isPrime[i]) { for(int j=i*i; j<n; j+=i) isPrime[j] = false; } } vector<int> res; for(int i=2; i<n; ++i) if(isPrime[i]) res.push_back(i); return res; } ``` 3. 矩阵路径问题(LeetCode 79) 问题:在二维字符矩阵中查找单词 ```cpp bool exist(vector<vector<char>>& board, string word) { vector<vector<bool>> visited(board.size(), vector<bool>(board[0].size(), false)); for(int i=0; i<board.size(); ++i) for(int j=0; j<board[0].size(); ++j) if(dfs(board, visited, i, j, word, 0)) return true; return false; } bool dfs(...) { if(...) return true; visited[i][j] = true; // 标记当前位置已访问 // 四个方向递归搜索 visited[i][j] = false; // 回溯时恢复状态 return false; } ``` 三、优化技巧 1. 原地标记:当允许修改输入数组时,可直接修改原数组 ```cpp // 将访问过的元素标记为'#' board[i][j] = '#'; // 回溯时恢复原值 board[i][j] = original; ``` 2. 位运算压缩:当数据范围较大时,可用bitset优化空间 ```cpp bitset<1000000> flag; // 仅需125KB内存 ``` 四、注意事项 1. 初始化问题:务必正确初始化标记数组 2. 下标映射:当元素值可能为负数时,需进行偏移处理 3. 空间复杂度:数据量极大时需考虑内存限制 五、常见变种题型 1. 寻找消失的数字(LeetCode 448) 2. 矩阵中的最长递增路径(LeetCode 329) 3. 解数独问题(LeetCode 37) 掌握标记数组技巧能有效解决约30%的数组/矩阵类算法题,建议通过LeetCode对应tag的题目进行专项训练。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值