📜  门| GATE-CS-2016(Set 1)|问题14(1)

📅  最后修改于: 2023-12-03 15:12:43.018000             🧑  作者: Mango

门| GATE-CS-2016(Set 1)|问题14

这是一道GATE-CS-2016考试中的问题14,考察的是计算机科学专业的学生的知识深度和能力。

问题描述

有两个全局数组 s 和 t,长度分别为 n 和 m。有一个2维数组 shift,其中shift[i] = [direction, amount] 表示 s 的前 i 个元素将按方向(向左或向右)移动 amount 个位置。即,shift[i][0] = 0 表示向左移动,shift[i][0] = 1 表示向右移动。

返回在执行所有shifts后,t 是否仍然等于 s。

示例

输入:

s = [1,2,3,4,5], t = [3,4,5,1,2]

shift = [[0,1],[1,2]]

输出: true

解释:

因为以下操作后 t 变成了 s:

shift[0] = [0,1] :数字序列变为 [2,3,4,5,1].

shift[1] = [1,2] :数字序列变为 [2,3,4,1,5].

s 和 t 未发生改变,所以返回true。

要求

你需要完成函数bool canShifted(int[] s, int[] t, int[][] shift) 的实现。

其中:

s.length, t.length <= 100; shift.length <= 100; shift[i].length == 2; 0 <= shift[i][0] <= 1; 0 <= shift[i][1] <= 100; 这个问题可以用模拟的方式解决,但是还有更高效的方法吗?

解决方案

为了避免不必要的数组操作,我们可以考虑将 shift[i] 转化成 shift[0] 和 shift[1] 分别表示向左和向右的移动量(shift[i][0] = 0 表示左移,shift[i][0] = 1 表示右移)。然后我们可以遍历 shift[],计算偏移量 left 和 right。最终,判断 t 是否等于 s 的循环移位结果即可。

下面是实现方案的代码片段(Java语言):

public boolean canShifted(int[] s, int[] t, int[][] shift) {
    int left = 0, right = 0;
    for (int i = 0; i < shift.length; i++) {
        if (shift[i][0] == 0) {
            left += shift[i][1];
        } else {
            right += shift[i][1];
        }
    }
    int len = s.length;
    right = right % len;
    left = left % len;
    if (left + right > len) {
        left = left + right - len;
        right = len - left;
        left = len - right - left;
    }
    int[] s_shifted = new int[len];
    for (int i = 0; i < len; i++) {
        if (i + left >= len) {
            s_shifted[i + left - len] = s[i];
        } else {
            s_shifted[i + left] = s[i];
        }
    }
    for (int i = 0; i < len; i++) {
        if (s_shifted[i] != t[i]) {
            return false;
        }
    }
    return true;
}

代码中,我们先计算出数组 s 需要向左或向右移动的量,然后将其转化为最终左移与右移的量。接着创建一个新的数组 s_shifted,将 s 中的元素按偏移量从前往后排列。最后比较两个数组元素是否相等。