📌  相关文章
📜  Java程序在K循环移位后将给定数组分成两半后使用按位或查找数组和(1)

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

Java程序在K循环移位后将给定数组分成两半后使用按位或查找数组和

在处理数组时,常常会用到循环移位的操作,即将数组的元素向左或向右移动k个位置。此外,我们还需要将数组分成两半,并使用按位或操作查找数组和。下面是Java代码示例。

1. 循环移位

循环移位是指将数组的元素向左或向右移动k个位置,并将超出数组长度的元素移动到数组的首尾部分。下面是Java代码示例:

public static void rotate(int[] nums, int k) {
    k %= nums.length;
    reverse(nums, 0, nums.length - 1);
    reverse(nums, 0, k - 1);
    reverse(nums, k, nums.length - 1);
}

public static void reverse(int[] nums, int start, int end) {
    while (start < end) {
        int temp = nums[start];
        nums[start] = nums[end];
        nums[end] = temp;
        start++;
        end--;
    }
}

在上述代码中,我们首先计算出k对数组长度的余数,以避免进行不必要的移位。接着,我们将数组分为前后两个部分,调用reverse方法进行翻转操作,最后再将两个部分合并即可。

2. 分割数组并使用按位或操作查找数组和

我们需要将数组分成两部分,并使用按位或操作查找数组和。下面是Java代码示例:

public static int sumSubarrayMins(int[] A) {
    Stack<Pair<Integer, Integer>> s = new Stack<>();
    int[] left = new int[A.length];
    int[] right = new int[A.length];

    // 求左边第一个小于当前元素的位置
    for (int i = 0; i < A.length; i++) {
        int count = 1;
        while (!s.isEmpty() && s.peek().getKey() > A[i]) {
            count += s.pop().getValue();
        }
        s.push(new Pair<>(A[i], count));
        left[i] = count;
    }

    // 求右边第一个小于当前元素的位置
    s.clear();
    for (int i = A.length - 1; i >= 0; i--) {
        int count = 1;
        while (!s.isEmpty() && s.peek().getKey() >= A[i]) {
            count += s.pop().getValue();
        }
        s.push(new Pair<>(A[i], count));
        right[i] = count;
    }

    // 按位或操作求和
    long ans = 0;
    int MOD = 1000000007;
    for (int i = 0; i < A.length; i++) {
        ans = (ans + (long) A[i] * left[i] * right[i]) % MOD;
    }
    return (int) ans;
}

在上述代码中,我们使用了栈来保存每个元素的值和出现次数。在计算左边小于当前元素的最近位置时,我们向前遍历数组,如果栈中元素的值大于当前元素,则将这些元素出栈并累加出栈元素的出现次数。然后将当前元素和次数加入栈中,并将次数赋值给左边数组中对应的元素。同样的,我们也可以计算出右边数组每个元素左边小于该元素的最近位置,然后将左右数组对应元素值按位或操作,并累加起来即可。

3. Markdown格式代码片段

循环移位代码片段:

public static void rotate(int[] nums, int k) {
    k %= nums.length;
    reverse(nums, 0, nums.length - 1);
    reverse(nums, 0, k - 1);
    reverse(nums, k, nums.length - 1);
}

public static void reverse(int[] nums, int start, int end) {
    while (start < end) {
        int temp = nums[start];
        nums[start] = nums[end];
        nums[end] = temp;
        start++;
        end--;
    }
}

分割数组并使用按位或操作查找数组和代码片段:

public static int sumSubarrayMins(int[] A) {
    Stack<Pair<Integer, Integer>> s = new Stack<>();
    int[] left = new int[A.length];
    int[] right = new int[A.length];

    // 求左边第一个小于当前元素的位置
    for (int i = 0; i < A.length; i++) {
        int count = 1;
        while (!s.isEmpty() && s.peek().getKey() > A[i]) {
            count += s.pop().getValue();
        }
        s.push(new Pair<>(A[i], count));
        left[i] = count;
    }

    // 求右边第一个小于当前元素的位置
    s.clear();
    for (int i = A.length - 1; i >= 0; i--) {
        int count = 1;
        while (!s.isEmpty() && s.peek().getKey() >= A[i]) {
            count += s.pop().getValue();
        }
        s.push(new Pair<>(A[i], count));
        right[i] = count;
    }

    // 按位或操作求和
    long ans = 0;
    int MOD = 1000000007;
    for (int i = 0; i < A.length; i++) {
        ans = (ans + (long) A[i] * left[i] * right[i]) % MOD;
    }
    return (int) ans;
}