C语言数组练习以及场景练习题

简介: C语言数组练习以及场景练习题

写了那么久的知识点梳理,今天来写点自己觉得不错的练习题来分享,顺便来巩固自己的知识点,和加强题型的解决方法的记忆。今天给大家带来的有数组的找数字题目,以及场景找凶手的题目,下面让我们来看看今天的第一道题目。


有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在。要求:时间复杂度小于O(N)。


大家看到题目是否有了自己的思路了呢?下面我展示一下答案。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
 
int Find_Num(int p[][4], int i, int j, int key)
{
  int x = 0;
  int y = j - 1;
  while (x < i && y < j)
  {
    if (p[x][y] > key)
    {
      y--;
    }
 
    if (p[x][y] < key)
    {
      x++;
    }
 
    if (p[x][y] == key)
    {
      return p[x][y];
    }
 
  }
 
  return 0;
 
 
 
 
}
 
 
 
 
int main()
{
  int ret = 0;
  int arr[4][4] = { {1,2,3,4},{5,6,7,8,},{11,12,13,14},{22,33,44,55} };
  int key = 0;
  
  printf("请输入你想查找的数字\n");
  scanf("%d", &key);
 
  ret=Find_Num(arr, 4, 4,key);
  if (ret != 0)
  {
    printf("数组中存在这个数字\n");
 
  }
  else
  {
    printf("数组中不存在这个数字\n");
 
  }
  return 0;
}


首先我们需要借助图来解析我的代码思路



首先我们从题目知道,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,那我们先按照题目设一些值。首先我们不能从第一行第一列一个一个往下找吧,不然这样就太耗费时间了,就不符合要求了。那怎么办呢,那我们就要想到一个奇妙的位置那就是右上角的位置,为什么要这样呢?首先在这个位置上我们首先对右上角的值,例如图中的4与Key进行对比,因为key大于4,那么就是要找比4大的数,也就是往下一行进行查找,因为在4的左边的数比4还要小。这样我们就可以排除掉一行的值,在下来也类似,8比Key大那么往小里找,8往下的值比8还大,那么舍弃掉这一列。直到找到Key与p[x][y]相等为止。


所以代码中就有这么些代码:

if (p[x][y] > key)
        {
            y--;
        }
 
        if (p[x][y] < key)
        {
            x++;
        }
 
        if (p[x][y] == key)
        {
            return p[x][y];
        }


接下来我们看第二题:

一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
编写一个函数找出这两个只出现一次的数字。

例如:
有数组的元素是:1,2,3,4,5,1,2,3,4,6
只有5和6只出现1次,要找出5和6.

看过我前面的文章的是不是觉得似曾相识呢?与前面不同的是,这个题目要找的是两个数这么一看,大家能否有思路解决这道题呢。下面先展示参考答案。

FindNum(int arr[], int* num1, int* num2,int n)
{
 
  int i = 0;
  int tem=0;
  for (i = 0; i < n; i++)
  {
    tem ^= arr[i];
  }
 
  int k = 0;
  for (i = 0; i < 32; i++)
  {
    if ((tem >> i) & 1 == 1)
       k = i;
 
  }
 
 
  for (i = 0; i < n; i++)
  {
    if (((arr[i] >> k) & 1) == 1)
    {
      *num1^= arr[i];
    }
 
    else
    {
      *num2^=arr[i];
    }
  }
 
}
 
 
 
 
int main()
{
  int arr[10] = { 1,2,3,4,76,4,3,2,1,45 };
  int sz = sizeof(arr) / sizeof(arr[2]);
  int num1 = 0;
  int num2 = 0;
  FindNum(arr, &num1, &num2, sz);
  printf("%d %d", num1, num2);
 
 
  return 0;
}


这道题要解释起来,我们还是得画图来理解:


解析:首先我们如图解所说要将数分成两部分,然后需要异或操作符。我们前面将过两个公式不知道大家是否记得:

a^a=0;

0^a=a;


这两个公式就可以让我们区分一个单次出现过的数,但是这里如何将数组的数区分成两部分呢?首先我们将数组中的所有数进行异或,那么我们最终异或得到的值存到tem中,如上方:这时tem=76^45 ,那么大家仔细一想异或操作符,相异为1,这是不是就是两个数的区别了,那么这时我们就可以想一下能否从这个地方找到方法区分两个数和其他数两两分到同一部分呢。这里我们就可以从32位比特上找到tem中为1的那一个比特位,(可看下图理解)然后将数组中的所有数为1的分为一部分,为0的分为一部分,这样我们就可以将数组的数分为两部分,然后不断异或就可以得到两个数,这既是那两个数组中只出现一次的数。如图:

代码解释:

将tem进行异或后,用tem借助>>操作符找到为1的比特位,然后再用>>和^操作符进行分类,最后得到两个数,打印即可。


最后一道场景题:

日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。

以下为4个嫌疑犯的供词:

A说:不是我。
B说:是C。
C说:是D。
D说:C在胡说
已知3个人说了真话,1个人说的是假话。


现在请根据这些信息,写一个程序来确定到底谁是凶手。


根据这个场景各位能否想到方法来找出凶手呢?下面展示参考代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  char Killer;
 
  for (Killer = 'a'; Killer <= 'd'; Killer++)
  {
    if (((Killer != 'a') + (Killer =='c') + (Killer == 'd') + (Killer != 'd')) == 3)
    {
      break;
    }
  }
  printf("%c是凶手\n", Killer);
  return 0;
}
 


这么一看是否发现其实代码很简洁,但是这道题却很考验对代码的熟练和思维。


从题目中我们知道四个人中有一个人是凶手,所有四个人中有三个人说的话是真的,只有凶手说假的话。那么我们就需要思考出怎么在代码中确定什么时候是3个人说真话,1个人说假话得场景。


代码中我们就运用到判断语句,我们知道在C语言中判断语句中,真为1,假为0,这时我们可以根据四个人讲的话作为条件,进行判断,最后相加起来,当为3时,就是凶手,这时我们就需要代码轮番将四个人假设为凶手,那我们也要知道字符++,也是根据ASCII码值来储存,++就会得到下一个字符了。这么一解释,相信各位就已经能看懂代码了吧。

文章已到篇尾,能看到这里也谢谢您的支持了,可以的话记得三连哟。

 


目录
相关文章
|
2月前
|
存储 C语言 C++
【C语言数组】
【C语言数组】
|
1天前
|
C语言
顺序表数组法构建(C语言描述)
如何使用C语言通过数组方法构建有序顺序表,包括顺序表的创建、插入、删除和打印等。
9 2
|
7天前
|
C语言 C++
【C语言】解决不同场景字符串问题:巧妙运用字符串函数
【C语言】解决不同场景字符串问题:巧妙运用字符串函数
|
7天前
|
存储 编译器 C语言
【C语言】数组(一维、二维数组的简单介绍)
【C语言】数组(一维、二维数组的简单介绍)
|
3天前
|
C语言
C语言数组练习之让生锈大脑转一下(练习篇)
C语言数组练习之让生锈大脑转一下(练习篇)
19 0
|
5天前
|
存储 C语言
初识C语言4——数组
初识C语言4——数组
36 0
|
1月前
|
存储 编译器 C语言
【C语言基础考研向】09 一维数组
数组是一种有序集合,用于存储相同类型的数据,便于统一操作与管理。例如,将衣柜底层划分为10个格子存放鞋子,便于快速定位。在C语言中,数组定义格式为 `类型说明符数组名[常量表达式];`,如 `int a[10];` 表示定义了一个包含10个整数的数组。数组初始化时可以直接赋值,也可以部分赋值,且数组长度必须固定。数组在内存中连续存储,访问时需注意下标范围,避免越界导致数据异常。数组作为参数传递时,传递的是首地址,修改会影响原数组。
|
1月前
|
存储 C语言
【C语言基础考研向】10 字符数组初始化及传递和scanf 读取字符串
本文介绍了C语言中字符数组的初始化方法及其在函数间传递的注意事项。字符数组初始化有两种方式:逐个字符赋值或整体初始化字符串。实际工作中常用后者,如`char c[10]=&quot;hello&quot;`。示例代码展示了如何初始化及传递字符数组,并解释了为何未正确添加结束符`\0`会导致乱码。此外,还讨论了`scanf`函数读取字符串时忽略空格和回车的特点。
|
7天前
|
存储 编译器 C语言
【C语言篇】数组和函数的实践:扫雷游戏(附源码)
【C语言篇】数组和函数的实践:扫雷游戏(附源码)
16 0
|
7天前
|
编译器 C语言
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)