《力扣算法訓練提高》圖解數組篇-打卡數組統計-【189】旋轉數組

《力扣算法訓練提高》圖解數組篇-打卡數組統計-【189】旋轉數組

今日份打卡題[189. 旋轉數組]

打卡

給定一個數組,將數組中的元素向右移動 k 個位置,其中 k 是非負數。算法

具體描述數組

算法描述

解題討論

算法討論1

算法討論2

討論概括一:輔助數組,劃分旋轉區域

第一步:根據數組長度 N 和跨步 K 計算出須要轉移至數組頭部的元素個數
第二步:將數組劃分爲兩個區域
	注意:(邏輯區域,思想區域,這裏是爲了方便理解,不須要真實狀態標註)
	區域一:須要旋轉到右邊的數(頭部須要旋轉到尾部的元素)
	區域二:須要旋轉到左邊的數(尾部須要旋轉到頭部的元素)
第三步:遷移數據到輔助數組
	先遷移區域二,在遷移區域一
第四步:拷貝回原數組

區域劃分圖動畫

區域劃分

動畫模擬code

區域旋轉動畫

示例一:輔助數組,劃分旋轉區域blog

public void rotate(int[] nums, int k) {

    // 計算尾部須要移至頭部元素個數
    k %= nums.length;

    int N = nums.length;
    int j = 0;
    int[] help = new int[nums.length];

    // 歸位區域二
    // 即歸位須要移至頭部的元素
    for (int i = N - k; i < N; i++) {
        help[j++] = nums[i];
    }

    // 歸位區域一
    // 即歸位須要移至尾部的元素
    for (int i = 0; i < N - k; i++) {
        help[j++] = nums[i];
    }

    System.arraycopy(help, 0, nums, 0, N);
}

複雜度分析排序

時間複雜度:O(n)。遍歷數組須要 O(n) 的時間。
空間複雜度:O(n)。須要輔助數組。

討論概括二:輔助數組,前世此生

重點:數組元素 a[i] 經過潘多拉魔盒找到此生(a[i] 旋轉後在新的位置下標 j)

遍歷數組,找到前世 a[i] 的此生 j, 並安排到輔助數組對應的位置

魔盒:j = (i+k) % N

前世此生圖入門

前世此生圖

動畫模擬基礎

前世此生動畫

示例二:輔助數組,前世此生進階

public void rotate(int[] nums, int k) {
    int n = nums.length;
    int[] help = new int[n];
    for (int i = 0; i < n; ++i) {
        // 旋轉 k, 至關於 nums[i] 元素向後跨步 k 個下標
        // nums 數組下標範圍是 [0, N-1]
        // 跨步後下標超過N-1,從 0 繼續跨步
        // 計算 nums[i] 旋轉後在輔助數組中的相對位置
        int m = (i + k) % n;
        help[m] = nums[i];
    }
    System.arraycopy(help, 0, nums, 0, n);
}

複雜度分析遍歷

時間複雜度:O(n)。其中 n 爲數組的長度。
空間複雜度:O(n)。須要額外空間。

討論概括三:翻轉數組

概括一中,囧囧劃分了旋轉區域,利用輔助數組實現區域旋轉,實現了數組旋轉的目的。

實際上,咱們不須要藉助輔助數組也能實現區域旋轉,達到交換目的。

首先仍是利用模運算計算出須要轉移到數組頭部的元素個數。

在經過翻轉數組實現旋轉。

1 2 3 4 5 6 7   K=3

第一步:根據數組長度 N 和跨步 K 計算出須要轉移至數組頭部的元素個數
第二步:將數組劃分爲兩個區域
	注意:(邏輯區域,思想區域,這裏是爲了方便理解,不須要真實狀態標註)
	區域一:須要旋轉到右邊的數(頭部須要旋轉到尾部的元素)
	1 2 3 4
	
	區域二:須要旋轉到左邊的數(尾部須要旋轉到頭部的元素)
	5 6 7
	
第三步:翻轉整個數組 
	7 6 5 4 3 2 1
第四部:翻轉區域二,在翻轉區域一
	翻轉區域二   5 6 7
	翻轉區域一   1 2 3 4
	
	5 6 7 1 2 3 4

動畫模擬

翻轉數組動畫

示例三:翻轉數組

public 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);
}

// 翻轉 [start, end] 範圍內的數
public void reverse(int[] nums, int start, int end) {
    while (start < end) {
        int temp = nums[start];
        nums[start] = nums[end];
        nums[end] = temp;
        start += 1;
        end -= 1;
    }
}

勇敢牛牛

短話長說

學算法先學什麼?什麼階段該刷什麼題?

關注我,平常打卡算法圖解。

按照力扣題目類別結構化排序刷題,從低階到高階,圖解算法(更新中...),有興趣的童鞋,歡迎一塊兒從小白開始零基礎刷力扣,共同進步!

短話長說

回覆:678,獲取已分類好的部分刷題順序,後續內容會持續更新,感興趣的小夥伴自由拿取!

另外,有關分類,求小夥伴們不要再問我最後一類的起名了,奇技淫巧是個褒義詞,意思是指新奇的技藝和做品。

力扣修煉體系題目,題目分類及推薦刷題順序及題解

目前暫定劃分爲四個階段:

算法低階入門篇--武者鍛體

算法中級進階篇--武皇煉心

算法高階強化篇--武帝粹魂

算法奇技淫巧篇--戰鬥祕典

以上分類原諒我有個修仙夢...

缺漏內容,正在努力整理中...

gzw

相關文章
相關標籤/搜索