1. 程式人生 > >PAT-BASIC1008——陣列元素迴圈右移問題

PAT-BASIC1008——陣列元素迴圈右移問題

題目描述:

知識點:陣列

思路:每個位置只移動一次,用一個數組flag來標記該位置是否已經被移動過

如果每次只向右移動一位,那我們對於每個位置就需要移動M次,太浪費時間了。事實上,對於一個位置i,我們是知道其下一個位置將會是(i + M) % N。

我們為什麼要每次只移動1位呢?但是如果一次性移動M位又有個問題,位置i到達位置(i + M) % N,那麼原來(i + M) % N位置的值也將移動到下一個位置,什麼時候其下一個位置剛好是位置i,以此形成一個迴圈呢?

所以,在移動的時候,我們需要一個標記陣列flag來記錄該位置是否已經被移動。在遍歷原陣列移動的時候,如果該位置已經被移動過了,顯然我們不需要再次移動該位置。否則,就移動該位置,並且帶動一系列值一起移動。

時間複雜度是O(N),空間複雜度是O(1)。

C++程式碼:

#include<iostream>
#include<vector>

using namespace std;

int main() {
	int n;
	int m;
	cin >> n >> m;

	if (m >= n) {
		m %= n;
	}

	vector<int> array;
	for (int i = 0; i < n; i++) {
		int temp;
		cin >> temp;
		array.push_back(temp);
	}

	vector<bool> flag;
	for (int i = 0; i < n; i++) {
		flag.push_back(false);
	}

	for (int i = 0; i < array.size(); i++) {
		if (flag[i]) {
			continue;
		}
		flag[i] = true;
		int temp = array[i];
		int index = i;
		while (true) {
			int next = index - m;
			if (next < 0) {
				next += n;
			}
			if (next == i) {
				array[index] = temp;
				break;
			}
			array[index] = array[next];
			flag[next] = true;
			index = next;
		}
	}
	
	for (int i = 0; i < array.size(); i++) {
		cout << array[i];
		if (i != array.size() - 1) {
			cout << " ";
		}
	}
}

C++解題報告:

JAVA程式碼:

import java.util.ArrayList;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) {
            nums[i] = scanner.nextInt();
        }
        if(m >= n){
            m = m % n;
        }
        boolean[] flag = new boolean[n];
        for (int i = 0; i < n; i++) {
            if(flag[i]){
                continue;
            }
            ArrayList<Integer> arrayList = new ArrayList<>();
            arrayList.add(i);
            for (int j = 1;; j++) {
                if((i + j * m) % n == i){
                    break;
                }
                arrayList.add((i + j * m) % n);
            }
            remove(nums, arrayList);
            for (int j = 0; j < arrayList.size(); j++) {
                flag[arrayList.get(j)] = true;
            }
        }

        for (int i = 0; i < n; i++) {
            System.out.print(nums[i]);
            if(i != n - 1){
                System.out.print(" ");
            }
        }
    }

    private static void remove(int[] nums, ArrayList<Integer> arrayList){
        int temp = nums[arrayList.get(arrayList.size() - 1)];
        for (int i = arrayList.size() - 1; i >= 1; i--) {
            nums[arrayList.get(i)] = nums[arrayList.get(i - 1)];
        }
        nums[arrayList.get(0)] = temp;
    }
}

JAVA解題報告: