1. 程式人生 > 實用技巧 >陣列巢狀(力扣第565題)

陣列巢狀(力扣第565題)

565.陣列巢狀

​ 索引從0開始長度為N的陣列A,包含0到N - 1的所有整數。找到最大的集合S並返回其大小,其中 S[i] = {A[i], A[A[i]], A[A[A[i]]], ... }且遵守以下的規則。假設選擇索引為i的元素A[i]為S的第一個元素,S的下一個元素應該是A[A[i]],之後是A[A[A[i]]]... 以此類推,不斷新增直到S出現重複的元素。

示例 1:

輸入: A = [5,4,0,3,1,6,2]
輸出: 4
解釋: 
A[0] = 5, A[1] = 4, A[2] = 0, A[3] = 3, A[4] = 1, A[5] = 6, A[6] = 2.

其中一種最長的 S[K]:
S[0] = {A[0], A[5], A[6], A[2]} = {5, 6, 2, 0}

提示:

N是[1, 20,000]之間的整數。
A中不含有重複的元素。
A中的元素大小在[0, N-1]之間。

分析:

​ 可以將S集合看作是一個環形連結串列,那麼集合的大小就是環形連結串列的長度。因為陣列的索引是0N-1,陣列的元素值也是0N-1,所以元素值就可以看作是下一個結點的“地址”,比如對於示例1,S[0]集合來說,就是形成了這樣一個環形連結串列:

​ 0->5->6->2->0,

​ 可以定義一個隊首指標head,head = nums[0],然後定義一個遍歷指標變數point,初始值指向隊首元素的下一個元素:point=nums[head],然後它進行的向後走的操作是:point=nums[point]

​ 當head == point時,說明環形連結串列走完。

​ 因此,我們對陣列中每個元素進行這樣的操作之後,求出最大值就是最終的結果。

public int arrayNesting(int[] nums) {
    if (nums == null || nums.length == 0){
        return 0;
    }
    int maxLength = 0;
    for (int i = 0; i < nums.length; i++) {

            int head = nums[i];
            int point = nums[head];
            int curLength = 1;
            while (point != head) {
                point = nums[point];
                curLength++;
            }
            if (curLength > maxLength) {
                maxLength = curLength;
            }

    }
    return maxLength;
}

​ 該方法雖然解決了問題,但是時間複雜度太高,效能不好,有點像暴力法了。其實可以優化一下的,因為我們要求的是長度最大的那個環形連結串列的長度,而每個環形連結串列都是一個閉環,即環外的元素永遠不會指向環中的元素,環中的元素也不會指向環外元素,求所有的S集合的操作相當於將原始陣列的元素劃分為了幾個不相交的集合。那麼既然是一個閉環,那麼從環中任何一個元素出發,最終形成的都是相同的環,長度自然也就相同。既然這樣就無需對原始陣列逐個遍歷求長度了,而是對於同一個環中的元素,訪問過之後就無需再訪問了。這樣會大大節省時間。

​ 例如:

​ S[0] : 0->5->6->2->0

​ S[2] : 2->0->5->6->2

​ S[5] : 5->6->2->0->5

public int arrayNesting2(int[] nums) {
    if (nums == null || nums.length == 0){
        return 0;
    }
    int maxLength = 0;
    for (int i = 0; i < nums.length; i++) {

        int count = 0;

        for (int j = i; nums[j] != -1 ; ) {
            count++;
            int temp = nums[j];
            nums[j] = -1;
            j = temp;
        }

        if (count > maxLength){
            maxLength = count;
        }
    }

    return maxLength;
}