【问题标题】:Creating a Boolean function that determines if two arrays are shift equivalent创建一个布尔函数来确定两个数组是否是等价的
【发布时间】:2013-01-16 06:50:24
【问题描述】:

两个数组:

a[] = {1 2 3 4}
b[] = {3 4 1 2}

底部数组只是顶部数组向右移动了两个位置。如果顶部数组可以右移来创建底部数组,我们称它们为等价移位。

这是我尝试创建一个函数(我需要使用布尔函数)来确定两个数组是否“移位等效”:

#include <iostream>
using namespace std;

bool equivalent(int a[], int b[], int size) {

    int value; // if 1 returns as truth
    int k; // counter to compare both arrays

    for (int j = 0; j <= size; j++) {
        for (int i = 0; i <= size; i++) {
            a[i] = a[i + j];
        }
    }

    for (k = 0; k <= size; k++) {
        if (a[k] != b[k]) {
            value = 0;
        } else value = 1;
    }

    return (value == 1);
}

int main() {
    int n;
    cout << "Please input a size " << endl;
    cin >> n;

    int *mtrx = new int[n];
    int *mtrx1 = new int[n];
    int x;
    for (x = 0; x < n; x++) {
        cout << "Please make entries for the first array: " << endl;
        cin >> mtrx[x];
    }
    x = 0;
    for (x = 0; x < n; x++) {
        cout << "Please make entries for the 2nd array: " << endl;
        cin >> mtrx1[x];
    }

    bool answr = equivalent(mtrx, mtrx1, n = n - 1);

    if (answr) {
        cout << "They are shift equivalent." << endl;
    } else {
        cout << "They are not shift equivalent." << endl;
    }

    delete[] mtrx;
    delete[] mtrx1;

    system("PAUSE");
    return 0;
}

当我执行我的程序时,我使用array1 = {1 2 3}array2 = {3 1 2} 来测试移位等效性。他们应该是,但我的程序说他们不是。

【问题讨论】:

  • 你的大括号风格(曾经)很奇怪。
  • 我发现空间编辑更奇怪。
  • 什么是大括号样式?对不起,我是编程新手。
  • 你的逻辑也没有意义..
  • 对于大括号样式,您是否注意到在@Rapptz 的编辑之后,所有{ 都在表达式之后开始,而} 出现在其自身行的开头?这几乎是最常见的样式,并且清楚地显示了块的结束位置。你的风格在最后一个语句的末尾出现了},这非常令人困惑和不明显。

标签: c++ function boolean dynamic-arrays boolean-expression


【解决方案1】:

我在您的代码中看到的一个问题是您访问数组之外​​的内存。如果添加两个索引,则必须确保它们“环绕”如果你想处理你的数组循环。这可以通过模数来完成。而不是

a[i + j]

你应该写

a[(i + j) % size]

我将您的算法分为两部分:首先,编写一个函数来测试a 是否等于b,并带有shift 的移位。然后,在第二个函数(最后一个 equivalent 函数)中,测试 shift 的所有可能值。

bool equivalentFixed(int a[], int b[], int size, int shift) {
    for (int i = 0; i < size; ++i) {
        if (a[i] != a[(i + shift) % size])
            return false;
    }
    return true;
}

bool equivalent(int a[], int b[], int size) {
    for (int shift = 0; shift < size; ++shift) {
        if (equivalentFixed(a, b, size, shift))
            return true;
    }
    return false;
}

如果仔细观察,如果数组是等价的,则看不到任何保存(存储)值的局部变量。实际上,您的代码在这里也有问题,因为您总是用新的状态覆盖旧状态,因为您比较的每个条目。因此,如果在扫描数组期间任何地方比较失败,但最后一个条目比较相等,则返回“是的,它们相等”,因为您已经覆盖了状态。

现在看看我的equivalent 实现。如果数组比较相等,我会扫描不同的偏移量 (shift)。让我们关注这个函数,而不是在另一个函数中如何进行比较。关键是:如果对于 any 移位它们比较相等,则我们必须返回 true,而不是对于 最后一个,而不是对于 all。 p>

解决这个问题的想法是在找到解决方案时打破循环(停止)。您甚至可以返回整个函数,因为您知道完整的返回值,即true

如果对于没有可能的移位,比较为真,我们没有发现任何可能的移位,因此它们不是“等效移位”。

我使用了一种非常相似的方法来实现两个具有固定移位的数组的比较 (equivalentFixed)。你能解释一下这是怎么做到的吗?

【讨论】:

  • 换班?你的意思是我应该创建一个名为 shift 的函数?
  • 另外,你为什么要把它们分成两个函数?我很好奇。
  • @paddy 给我看一个更好的。此外,这是关于学习微不足道的代码,而不是算法复杂性。
  • @Chase 请看我的编辑。我尽力解释我为什么这样做。它使代码更干净。
  • @Chase 关于“班次班次”:我的意思是固定班次。我给它起了一个名字,它是shift。对不起,我不想在这里混淆你。 ;)
【解决方案2】:

你在这里得到i+j&gt;size

a[i]=a[i+j]; 

这里只是一个小变化,使整个函数只包含一个函数:(这是一种罕见的情况,使用 dynosaur goto 很好 - 摆脱内部循环,而不引入新的时间变量)

#include <iostream>
using namespace std;

bool equivalent(int a[], int b[], int size) 
{
    for (int j = 0; j < size; j++) 
    {
        for (int i = 0; i < size; i++) 
        {
            if (a[i] != b[(i + j)%size]) goto next_shift;
        }
        return true;
        next_shift: ;
    }
    return false;
}

int main() {
    int n;
    cout << "Please input a size " << endl;
    cin >> n;

    int *mtrx = new int[n];
    int *mtrx1 = new int[n];
    int x;
    for (x = 0; x < n; x++) {
        cout << "Please make entries for the first array: " << endl;
        cin >> mtrx[x];
    }
    x = 0;
    for (x = 0; x < n; x++) {
        cout << "Please make entries for the 2nd array: " << endl;
        cin >> mtrx1[x];
    }

    bool answr = equivalent(mtrx, mtrx1, n );

    if (answr) {
        cout << "They are shift equivalent." << endl;
    } else {
        cout << "They are not shift equivalent." << endl;
    }

    delete[] mtrx;
    delete[] mtrx1;

    system("PAUSE");
    return 0;
}

编辑: 来自:C++ 编程语言。第三版。 Bjarne Stroustrup

6.3.4 转到 [expr.goto] C++拥有臭名昭著的go o t o:

goto identifier ;
identifier : statement

go t o 在一般高级编程中几乎没有用处

goto 在普通代码中的少数合理用途之一是破坏 从嵌套循环或 switch 语句中跳出(break 跳出 只有最里面的封闭循环或 switch 语句)。

例如:

voidf ()
{
int i ;
int j ;
for (i = 0 ; i <n ; i ++)
for (j = 0 ; j <m ; j ++) i f (nm [i ][j ] == a ) goto found ;
// not found
// ...
found :
// nm[i][j] == a
}

【讨论】:

  • @leemes 是的,认真的:-)。见编辑。
猜你喜欢
  • 2020-08-30
  • 1970-01-01
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
相关资源
最近更新 更多