0

好的,我不知道这是否是一个有效的问题,但我在这里发帖是因为我不知道还有什么地方可以解决这个问题。这半年我刚开始在大学学习编程,我们刚刚参加了期末考试,但我没有通过。基本上,有 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

这是我无法解决的部分:

我们的测试问我们:12点到13:00有多少人登录?

一开始我是

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 开始所有人。老实说,我什至不知道如何开始那个。

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

4

3 回答 3

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;

如果我在他们从 12:00 到 12:59 登录时增加计数,您可以在 1 中进行 2 次检查。您是否需要排除已注销的人?

最长时间码:

//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;

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

我没有花时间写“好代码”。但是你问它是怎么做到的,我想这已经足够理解了吧?

我没有测试代码,而是用记事本写的。所以我不知道它是否会编译。

于 2013-01-10T12:53:22.130 回答
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 )
                    }
                }
            }
        }
    }
}
于 2013-01-10T13:04:07.440 回答
0

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

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

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

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

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

于 2013-01-10T12:56:58.950 回答