C ++简单的数组元素比较

时间:2013-01-10 12:12:37

标签: c++ arrays

好吧我不知道这是否是一个有效的问题,但我在这里发帖是因为我不知道还有什么地方可以解决这个问题。我刚刚开始在大学学习半年的编程,我们刚刚参加了期末考试,但我失败了。基本上,有4个问题,而第二个看起来很容易,实际上很棘手,我只是无法弄清楚它应该如何完成。

基本上问题是:有一家银行,当人们登录做生意时,你需要编写一个程序来记录他们登录的时间(0-24h),分钟(0-59),他们选择的交易类型(1用于登录银行卡,-1用于登出同一张银行卡,2用于输入账户,2用于提取)最后是他们的银行账号(如果他们按下先前1或-1),或者他们撤回或投入的金额(如果他们选择2或-2)。

基本上我们就是这样做的:

int n; //size of the array or number of ppl who transacted that day
cin >> n;
int bank[n][4];
for (int i=0; i<n; ++i)
{
  cin >> bank[n][0];
  cin >> bank[n][1];
  cin >> bank[n][2];
  cin >> bank[n][3];
}

这会填满所有信息,然后

在白天,4个客户的输入样本基本上是这样的:

  1. 11 40 1 458965
  2. 12 20 2 6000
  3. 15 40 -1 458965
  4. 16 25 -2 18000
  5. 这是我无法解决的部分:

    我们的测试告诉我们:有多少人从12点钟到13点钟登录?

    起初我做了

    int count=0;
    for (int i=0; i<n; ++i)
    {
      if (bank[i][0]==12)
    {
      count=count+1;
    }
    }
    
    cout << count;
    

    问题在于,它不会考虑在12之前使用第三列中的1登录的人,但是在晚于1时使用-1注销。这意味着他们仍然在12点到1点之间登录。

    然后我做了

    int count=0;
    for (int i=0; i<n; ++i)
    {
      if (bank[i][0]==12)
      {
        count=count+1;
      }
      if (bank[i][2]==-1)
      {
        count=count+1;
      }
    }
    
    cout << count;
    

    然后我意识到这会计算一些登录两次,因为如果他们以12登录,例如1,那么在3点钟退出时输入-1将计算一个人两次。

    它还告诉我们任何人登录的最长时间,假设银行在24:00将所有人开除。老实说,我甚至不确定如何开始那个。

    编辑:SORRY我编辑了一堆东西,以使代码更清晰,更正确。我不太擅长这个,但原谅我的错误

3 个答案:

答案 0 :(得分:3)

我不知道银行系统是如何运作的。所以我为你做了一个最小的例子。 我也不知道你以前是否使用过课程,所以我没有写过。

我清理了你的代码:

//Use these enums
enum action { action_login = 1, action_logout = -1, action_input = 2, action_output = -2 };
enum information {information_time_h, information_time_m, information_action, information_bankNumber};

//Place this in the function you have
int peapelToInput = 0; //size of the array or number of ppl who transacted that day
cin >> peapelToInput;

for (int i=0; i<peapelToInput; ++i)
{
    //Maby add error handeling? When some one inputs a 'a', it won't do what you want. 
    cin bank[i][information_time_h];
    cin bank[i][information_time_m];
    cin bank[i][information_action];
    cin bank[i][information_bankNumber];
}

正如您所看到的,我通过添加枚举使代码更清晰。这使得开发变得更加容易。

登录代码:

int count=0;
int bankSize = bank.size(); //I guess it's a vector?
for (int i=0; i < bankSize; ++i)
{
    if (bank[i][information_time_h] == 12 && bank[i][information_action] == action_login)
        count++;
}
cout << "logins at 12:00 - 12:59:" << count << endl;

你可以在1中进行2次检查,如果我在12点到12点59分之间增加了计数。您是否需要排除已登出的人?

最长的时间代码:

//A function to search when he is logedout
int findLogoutIndex(int start, int accountNumber, XXX bank)
{
    int bankSize = bank.size();
    for (int i=start; i < bankSize; ++i)
        if( bank[i][information_action] == action_logout && bank[i][information_bankNumber] == accountNumber)
            return i;

    return -1; //Handle this error
}

//And how it workes
int logenst = 0;
int indexLongest = 0;
int bankSize = bank.size(); //I guess it's a vector?
for (int i=0; i < bankSize; ++i)
{
    if( bank[i][information_action] != action_login )
        continue;

    int logoutIndex = findLogoutIndex(i,bank[i][information_bankNumber],bank);
    //check if logoutIndex is not -1, or handle the error on an other way.

    int loginTimeHour = bank[logoutIndex][information_time_h] - bank[i][information_time_h];
    int loginTimeMinute = bank[logoutIndex][information_time_m] - bank[i][information_time_m];   
    int loginTime = (loginTimeHour * 100) + loginTimeMinute;

    if( logenst < loginTime)
    {
        logenst = loginTime;
        indexLongest = i;
    }
}
cout << "longest is: H:" << bank[indexLongest][information_time_h] << " M: " << bank[indexLongest][information_time_m] << endl;

您不需要保留时间格式,这种方式使比较容易得多。只需保存最长的登录时间及其索引号即可。这样您就可以轻松访问所需的所有数据。

我没有花时间写“好代码”。但是你问过它是如何完成的,我想这很好理解它?

我没有测试代码并在记事本中写了它。所以我不知道它是否会编译。

答案 1 :(得分:0)

您需要知道的第一件事是问题实际上是在问什么。在第一种情况下,从12点钟到1点钟登录了多少人?可能意味着多件事。这可能意味着在整个期间有多少人登录,或者在这两个小时之间的任何给定时间登录了多少人。不同之处在于,是否有人在12:15登录并在12:30退出。第二个问题是计算某人登录的最长时间,这可以同时完成。

一种可能的方法是管理从用户ID到登录时间的查找表。您可以线性地读取输入,只要有人登录,您就可以在表格中添加条目(acct, time)。当他们注销时,您查找帐号并计算时间差。如果差值大于最大值,则存储新的最大值。

对于第一个问题,在12处,您可以创建一组从该查找表登录的人员。每当有人在该时间和1之间退出时,您会发现该人是否在该集合中,如果有,则将其删除。当您在1之后找到第一个操作时,该集合包含从12到1整个时间段内登录的所有人的帐号。

如果问题是让所有人在此期间任何时间记录,而不是从1中删除那些在1之前注销的用户,则需要包含登录的新用户在这期间。在该期间结束时,该集合包含该期间内任何时间登录的所有用户。

您只需要对输入数据执行一次传递,这意味着您甚至不需要将所有事务存储在内存中,只需要存储上面所需的映射/集。操作的总成本为O(n log n)。 (免责声明:我没有做过数学计算,这是预感:))

答案 2 :(得分:0)

没有测试过这个。然而,所遵循的过程应该是正确的。

我确信这仍然可以在执行速度方面进行优化。

此外,我假设在12时你的意思是12:00,到时间1你的意思是13:00。

int main()
{
    int answer = 0;
    //  For each transaction
    for ( int i = 0; i < count; i++ ) {

        //  If logged in before 12:00
        //  bank[i][2] > 0 tells you user logged in.
        if ( bank[i][0] < 12 && bank[i][2] > 0 ) {
            //  Loop through each following transaction.
            for ( int j = i + 1; j < count; j++ ) {
                //  If logged out after 13:00
                if ( bank[j][0] > 13 && bank[j][2] < 0 ) {
                    //  Now to check if it was the same user who logged in earlier - how?:
                    //  Only way to differentiate is by comparing the transaction amounts and types.
                    if ( (bank[i][3] == bank[j][3]) && (bank[i][2] == -1*bank[j][2]) ) {    //  log-in code = -1 * log-out code.
                       answer++;    //  Number of transactions that spanned from before 12:00 till after 13:00.
                    //  Remember, a single person can't have multiple log-ins at the same time. ( assumption )
                    }
                }
            }
        }
    }
}