编程题实训-数组

第1关:二维数组中的元素查重

任务描述

设二维数组a[1..m, 1..n] 含有m*n 个整数。写一个算法判断a中所有元素是否互不相同。

编程要求

输入

多组数据,每组数据有m+1行,第一行为二维数组的行数m和列数n,之后m行为输入的二维数组。当n=0且m=0时输入结束。

输出

对于每组数据分别输出一行,若二维数组中存在相等元素则输出“YES”,否则输出“NO”。

#include<iostream>
#define MAXSIZE 124
using namespace std;
int IsEqual(int a[MAXSIZE][MAXSIZE],int m,int n)
{//判断a中所有元素是否互不相同,存在相等元素则返回1,输出“YES”,否则返回0,输出“NO”
/**************begin************/
    int i,j,p,k;
    for(i=0;i<m;i++)
        for(j=0;j<n-1;j++)        //判断a[i][j]是否重复
        {
            for(p=j+1;p<n;p++)        //用p来保存列,和同行其他元素比较
                if(a[i][j]==a[i][p])  //只要有一个相同,就返回1
                {
                    cout<<"YES"<<endl;
                    return 1;
                }
            for(k=i+1;k<m;k++)    //用k来保存行,和第i+1行及以后元素比较
                for(p=0;p<n;p++)    //用p来保存列,比较第k+1行的数据
                    if(a[i][j]==a[k][p])
                    {
                        cout<<"YES"<<endl;
                        return 1;
                    }
        }
    cout<<"NO"<<endl; //元素互不相同
    return 0;
    /**************end************/
}
int main()
{
    int m,n;    //行数m和列数n
    while(cin>>m>>n&&m!=0&&n!=0)
    {
        int a[MAXSIZE][MAXSIZE],i,j;
        for(i=0;i<m;i++)
            for(j=0;j<n;j++)
                cin>>a[i][j];		//输入二维数组
        IsEqual(a,m,n);        		//二维数组中的元素查重
    }
    return 0;
}

第2关:数组的正负数分割排序 

任务描述

设任意n个整数存放于数组A[1..n]中,试编写算法,将所有正数排在所有负数前面(要求:正(负)数序列中数的相对顺序不变,算法时间复杂度为O(n))。

编程要求

输入

多组数据,每组数据有两行,第一行为数组中存放的数的个数n,第二行为n个整数。当n=0时输入结束。

输出

对于每组数据分别输出一行,为分割排序后的数组。

#include <iostream>
using namespace std;
void SplitSort(int *A,int n)
{//正负数分割排序
/**************begin************/
    //这段代码的思路是使用冒泡排序的方式将正数移动到数组的左侧,而将负数移动到数组的右侧。通过每次比较相邻的两个元素,并交换它们的位置(如果需要),可以将整个数组分成两部分:正数和负数。这个过程从数组的最后一个元素开始,一直进行到数组的第一个元素。每次循环中,如果遇到一个负数,就将它与后面的正数交换位置,并将计数器 cnt 加 1。这样,最终得到的数组将满足要求:正数在前,负数在后。
    int i,j,cnt=0,temp;
	for(i=n-1;i>=0;i--)
	{
		if(A[i]<0)
		{
			cnt++;
			for(j=i;j<=n-cnt-1;j++)
			{
				temp=A[j+1];
				A[j+1]=A[j];
				A[j]=temp;
			}
		}
	}
    /**************end************/
}
void PrintA(int *A,int n)
{//依次输出数组中的数据
    for(int i=0;i<n;i++)
	{
		cout<<A[i];
		if(i!=n-1)cout<<" ";
		else cout<<endl;
	}
}
int main()
{
    int n;
    while(cin>>n)
    {
        if(n==0) break;
        int *A = new int[n];
        for(int i=0;i<n;i++) cin>>A[i];
        SplitSort(A,n);
        PrintA(A,n);
    }
    return 0;
}

第3关:数组的循环左移 

任务描述

设将n(n>1)个整数存放到一维数组R中。试设计一个在时间和空间两方面都尽可能高效的算法,将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据由(x0, x1…, xn-1)变换为(xp,xp+1,…,xn-1,x0,x1,…,xp-1)。

编程要求

输入

多组数据,每组数据有三行。第一行为一个整数n,代表数组R中有n个元素。第二行为数组R中的n个元素(元素之间用空格分隔)。第三行为一个整数p,代表将R中的序列循环左移p个位置。当n等于0时,输入结束。

输出

每组数据输出一行,为移动后的数组R中所存放的序列。每两个数之间用空格分隔。

#include <iostream>
using namespace std;
void Reverse(int R[],int left,int right)
{//将数组R中的数据原地逆置
/**************begin************/
    int i = left, j = right;
    while(i < j){
        int temp = R[i];
        R[i] = R[j];
        R[j] = temp;
        i++;
        j--;
    }
    /**************end************/
}
void LeftShift(int R[],int n,int p)
{//将长度为n的数组R中的数据循环左移p个位置
/**************begin************/
//如果p的值在0到n-1的范围内,这个函数会将数组R中的数据循环左移p个位置。具体步骤如下:

//首先,它会调用Reverse函数,将整个数组逆序。这一步其实是为了方便接下来的步骤,因为逆序后,最右边的元素就变到了最左边,左边的元素则变到了右边。
//然后,它再次调用Reverse函数,将前n-p个元素逆序。这样原来在右边的元素(也就是原来在左边的元素)就回到了它们原来在数组中的位置。
//最后,它再次调用Reverse函数,将剩下的p个元素逆序。这样原来在最右边的元素就移到了它们新的位置。
    if(p>0&&p<n)
    {
        Reverse(R,0,n-1);            //将全部数据逆置
        Reverse(R,0,n-p-1);         //将前n-p个数据逆置
        Reverse(R,n-p,n-1);         //将后p个数据逆置
    }
    /**************end************/
}
void PrintA(int R[],int n)
{//依次输出数组中的数据
    for(int i=0;i<n;i++)
    {
        cout<<R[i];
        if(i==n-1)
            cout<<endl;
        else
            cout<<" ";
    }
}
int main()
{
    int n;
    while(cin>>n)
    {
        if(n==0) break;
        int *R = new int[n];
        for(int i=0;i<n;i++)  //输入数据
        {
            cin>>R[i];
        }
        int p;          //p代表将R中的序列循环左移p个位置
        cin>>p;
        LeftShift(R,n,p);         //数组的循环左移
        PrintA(R,n);            //输出数据
    }
    return 0;
}

第4关:数组的主元素查询 

任务描述

已知一个整数序列A=(a0, a1,…an-1),其中0≤ai<n(0≤i<n)。若存在ap1=ap2…=apm=x 且m>n/2(0≤pk<n,1≤k≤m),则称x为A的主元素。例如A=(0,5,5,3,5,7,5,5),则5为主元素;又如A=(0,5,5,3,5,1,5,7),则A中没有主元素。假设A中的n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出A的主元素。若存在主元素,则输出该元素;否则输出-1。

编程要求

输入

多组数据,每组数据两行。第一行为一个整数n,代表数组中有n个元素。第二行为数组中的n个元素(元素之间用空格分隔)。当n等于0时,输入结束。

输出

每组数据输出一行,若数组中存在主元素,输出主元素的值,若数组中不存在主元素,则输出-1。

#include <iostream>
using namespace std;
int MainElement(int a[],int n)
{//求整数序列a的主元素
/**************begin************/
//数组的主元素定义为数组中出现次数大于等于数组长度一半的元素
    int cnt=1,i;            //cnt用来计数
    int key=a[0];          //key用来保存候选主元素,初始为a[0]
    for(i=1;i<n;i++)       //扫描数组,选取候选主元素
    {
        if(a[i]==key) cnt++;    //侯选主元素计数加1
        else
        {
            if(cnt>0) cnt--;   //非候选主元素计数减1
            else              //更换候选主元素,重新计数
            {
                key=a[i];
                cnt=1;
            }
        }
    }
    if(cnt>0)
        for(i=0,cnt=0;i<n;i++)     //统计候选主元素的实际出现次数
            if(a[i]==key) cnt++;
    if(cnt>n/2) return key;       //确认主元素
    else return -1;              //不存在主元素 
    /**************end************/
}
int main()
{
    int n;
    while(cin>>n)
    {
        if(n==0) break;
        int *a=new int[n];
        for(int i=0;i<n;i++)  //输入数据
        {
            cin>>a[i];
        }
        cout<<MainElement(a,n)<<endl;   //输出主元素的值
    }
    return 0;
}

第5关:找出数组中和为目标值的两个数 

 

任务描述

设计算法,找出数组中相加之和为目标值的两个数,并输出这两个数的下标。每组输入仅对应一种答案,相同的元素不能被重复利用。

编程要求

输入

多组数据,每组数据有三行,第一行为数组的大小n,第二行为n个元素(元素之间用空格分隔),第三行为目标值,当n=0时输入结束。

输出

对于每组数据分别输出一样,输出两个数的下标(元素间用空格分隔)。

#include<iostream>
using namespace std;
void CreateArray(int *a,int n)
{//创建数组
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
}
void Find(int *a,int n,int x)
{//找出数组中和为目标值的两个数
/**************begin************/
     for(int i=0;i<n;i++)         //遍历数组
    {
        for(int j=i+1;j<n;j++)    //每趟j指向a[i]后一个元素
        {
            if(a[i]+a[j]==x)        //判断是否满足相加之和为目标值
            {
                cout<<i<<" "<<j<< endl;
                break;
            }
        }
    }
    /**************end************/
}
int main()
{
	int n;
	while(cin>>n)
	{
	    if(n==0) break;
        int *a=new int[n];
	    CreateArray(a,n);     //创建数组
	    int x;
	    cin>>x;
	    Find(a,n,x);
	}
	return 0;
}

第6关:查找数组中缺失的数字 

任务描述

在大小为n的数组中,仅存在大小为[1,n]的数字,数组中的元素有些出现了两次,有些出现了一次,有的数字没有出现。设计一个算法在空间复杂度为O(1),时间复杂度为O(n)的情况下找到这些没有出现的数字。假设储存结果的数组不算在额外空间之内。

编程要求

输入

多组数据,每组数据有两行,第一行为数组的长度n,第二行为数组的n个元素(元素之间用空格分隔),当n=0时输入结束。

输出

对于每组数据分别输出一行,输出缺失的数据(元素之间用空格分隔),如果数据未缺失,输出Not Found。

#include<iostream>
#include<string>
#include<cmath>
#define MAXSIZE 1024
using namespace std;
void FindMissNumber(int *a,int n)
{//指定数字组中的位数
/**************begin************/
    // 通过将对应位置的元素变为负数来标记出现过的数字
     // 通过将对应位置的元素变为负数来标记出现过的数字
    // for (int i = 0; i < n; i++) {
    //     int index = abs(a[i]) - 1;
    //     if (a[index] > 0) {
    //         a[index] = -a[index];
    //     }
    // }

    // // 输出缺失的数字
    // bool found = false;
    // for (int i = 0; i < n; i++) {
    //     if (a[i] > 0) {
    //         cout << i + 1;
    //         found = true;

    //         // 判断是否为最后一个数字,不是则输出空格
    //         if (i != n - 1) {
    //             cout << " ";
    //         }
    //     }
    // }

    // // 如果没有缺失的数字,输出 "Not Found"
    // if (!found) {
    //     cout << "Not Found";
    // }

    // cout << endl;
    int index;    //待检查的牵引指数
    for(int i=0;i<n;i++)       //从原始数字组中查看列表中[i]数字组的第一个元素,然后将数字组元素的正确值作为倒数
    {
        index=abs(a[i])-1;    //更新要检查的牵引指数
        if(a[index]>0)
        {
            a[index]=a[index]*(-1);
        }
    }
    int *result=new int[MAXSIZE]{0};   //初始存储的结果数是结果
    int sub=0;                       
    for(int i=0;i<n;i++)
    {
        if(a[i]>0)           //如果a[i]大于0,输入结果编号组
        {
            result[sub++]=i+1;
        }
    }
    if(!sub)               //结果编号分组在标签Sub下,输出Not Found
    {
        cout<<"Not Found"<<endl;
    }
    else           //否则//输出存储的数据
    {
        for (int i=0;i<sub-1;i++)
                cout<<result[i]<< " ";
        cout<<result[sub - 1]<<endl;
    }

	/**************end************/
}
int main()
{
    int n;
    while (cin>>n)
    {
        if(n==0) break;
        int *a=new int[MAXSIZE]{0};    //初始编号集合中的所有元素都小于0
        for(int i=0;i<n;i++)            //将输入数据输入数据组
        {
            cin>>a[i];
        }
        FindMissNumber(a,n);
    }
    return 0;
}

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值