数组元素循环左移n个位置(JAVA)

问题描述:

将n(n>1)个整数存放在一维数组R中,设计一个在时间和空间两方面都尽可能高效的算法。 将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据(x0,x1,x2,…x(n-1))变换为(xp,x(p+1),…,x(n-1),x0,x1,…,x(p-1))


示例:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

左移4位

[5, 6, 7, 8, 9, 10, 1, 2, 3, 4]

中间数组辅助法

解题思路:定义一个中间数组temp[ ] 来辅助 R[ ]数组 的元素进行移动。

  1. 看下面代码的reverse方法,共有3个for循环。这3个for循环,是该算法实现元素循环左移的核心代码.

假设数组R = [1,2,3,4,5,6,7,8,9,10] ,向左移动4位 (p = 4)

  1. 第一个for循环:将数组R中,前p个元素 暂存到 temp数组中。
    cd
  2. 第二个for循环:将数组R中,后n-p个元素整体左移p个位置。(其实左移用在这里不太恰当,应该说:将后n-p个元素的值 赋给 前n-p个元素)
    cd
  3. 第三个for循环:将第一个 for 循环中,暂存在 temp 数组中的元素,依序赋值给 R数组中的后p个元素
    cd
public class Solution_3 {

    public static void reverse(int[] R, int p) {
        //中间数组
        int[] temp = new int[R.length];

        //将R数组中,前p个元素 暂存到 temp数组中
        for (int i = 0; i < p; i++) {
            temp[i] = R[i];
        }

        //将R数组中,后n-p个元素整体左移p个位置
        for (int i = p; i < R.length; i++) {
            R[i-p] = R[i];
        }

        //将暂存在 temp 数组中的元素,依序赋值给 R数组中的后p个元素
        int start = 0;
        for (int i = R.length-p; i < R.length; i++) {
            R[i] = temp[start++];
        }

    }

    public static void main(String[] args) {
        int[] R = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        int p = new Scanner(System.in).nextInt();
        reverse(R, p);
        //将数组以字符串格式打印输出
        System.out.println(Arrays.toString(R));
    }
}

时空复杂度:该算法只有单层循环,时间复杂度为O(n),因为外部内存中开了一个长度为n的中间数组,空间复杂度也为O(n)。


代码优化:前面reverse方法中,第一第二个代码我们可以进行合并。

解析:将元素暂存到temp数组 和 将R数组元素左移的步骤合并到一个for循环中。但需要注意的是,前面第一个for循环是直接将p个元素暂存到temp数组中。而合并后,是将n-p个元素暂存到temp数组中。因为R数组中有n-p个元素需要左移。

for (int i = 0; i < R.length-p; i++) { // T(n) = 3n = O(n)
    //将R数组中,前n-p个元素 暂存到 temp数组中
    temp[i] = R[i];
    //将R数组的后n-p个元素 赋值 给前面的n-p个元素
    R[i] = R[i + p];
}

时空复杂度:这一步并没有降低算法的时间复杂度,还是O(n)。仅仅只是代码量减少了



数组元素逆置法

解题思路:将R数组分割成a,b两个部分,然后分别将a,b两个部分的元素逆置,最后再将R数组整体逆置。所以需要三次调用元素逆置算法 。
cd

public class Solution_2 {

    private static void reverse(int[] R, int left, int right) {
        //数组元素互置算法(其实就是两个数的互换)
        for(int i = 0; i <= (right - left)/2; i++){
            int temp = R[left + i];
            R[left + i] = R[right - i];
            R[right - i] = temp;
        }
    }

    private static void move(int[] R, int n, int p) {
        //将数组中第一部分的元素逆置
        reverse(R,0,p - 1);

        //将数组中第二部分的元素逆置
        reverse(R, p,n - 1);

        //将整个数组的元素逆置
        reverse(R,0,n - 1);
    }

    public static void main(String[] args) {
        int[] R = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        int p = new Scanner(System.in).nextInt();
        move(R, R.length, p);
        //以字符串格式,将数组打印输出
        System.out.println(Arrays.toString(R));
    }
}

时空复杂度:该算法中用的都是一重循环,时间复杂度为O(n),因为基本没有用到外部内存,空间复杂度为O(1)。

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 要完成数组元素移动功能,可以使用如下代码实现: ``` n = len(arr) for i in range(x, n-1): arr[i] = arr[i+1] arr.pop() ``` 这段代码会从数组第x个位置开始,将后面的元素依次往前移动一个位置,最后删除最后一个元素。如果要重复若干次这样的删除,可以将其包装在一个循环。 ### 回答2: 这道题涉及到数组的元素删除和移动,可以通过循环数组操作完成。 首先,我们需要定义一个数组一个变量x,用来存放待删除元素的位置。接着,我们可以使用循环语句,遍历数组的所有元素。在循环,我们可以使用一个if语句,来判断当前元素是否是待删除元素。 如果是待删除元素,我们可以使用for循环数组操作,将后面的元素依次前移一个位置。具体实现可以参照以下代码: ``` // 定义一个数组 int arr[n]; // 定义待删除元素的位置 int x; // 遍历数组的所有元素 for(int i=0; i<n; i++) { // 判断当前元素是否是待删除元素 if(i == x) { // 如果是,使用for循环数组操作,将后面的元素依次前移一个位置 for(int j=i+1; j<n; j++) { arr[j-1] = arr[j]; } // 将数组的长度减1 n--; // 将删除后的元素位置减1,继续循环 i--; } } // 输出结果 for(int i=0; i<n; i++) { cout << arr[i] << " "; } ``` 需要注意的是,删除一个元素后,数组的长度会减1,因此循环的终点也要相应地做出调整。此外,在删除元素后,删除元素位置前面的元素下标不变,后面的元素下标要减1,因此需要将i的值减1,否则会跳过一个元素。 以上就是完成数组元素移动功能的基本思路和代码实现。需要注意的是,删除元素操作是O(n)时间复杂度的,因此如果需要进行多次删除操作,建议使用其他数据结构,如链表等。 ### 回答3: 首先,我们需要明确题目的要求。题目要求我们完成对一个数组的元素移动功能,具体地说,输入一个数x,将该数组的第x个位置的元素删除,后面的元素依次前进一个位置。这个步骤需要重复若干次,最终得到最终的结果。 那么,如何实现这个功能呢?首先,我们要明确数组删除元素的方式。对于一个普通的数组,不能直接删除一个元素,因为删除操作会导致数组的下标发生变化,后面的元素无法正确地被移动和访问。因此,在实现该功能时,我们需要借助另外一个数组。 具体而言,我们可以先创建一个长度为n-1的新数组,然后从原来的数组将除第x个位置之外的所有元素逐个拷贝到新数组,并将新数组作为最终结果返回。 在实现这个过程时,需要注意一些细节问题。首先,我们需要将第x个位置的元素删除,也就是不将其拷贝到新数组。其次,在将后面的元素依次向前移动的时候,我们可以通过将后面的元素依次依次向前赋值的方式实现。最后,需要重复多次这样的删除操作,直到最终得到结果为止。 总之,完成数组元素移动功能可以利用另外一个数组实现元素的删除,并通过多次重复删除操作实现最终的结果。在实现过程需要注意细节问题,例如如何删除元素、如何移动后续元素等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CD4356

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值