【前端js】實現劍指offer|leetcode(二)——數組題目集合


一、數組去重

1. 對排序數組去重(leetcode 26. 刪除排序數組中的重複項)

題目:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
給定一個排序數組,你需要在原地刪除重複出現的元素,使得每個元素只出現一次,返回移除後數組的新長度。
不要使用額外的數組空間,你必須在原地修改輸入數組並在使用 O(1) 額外空間的條件下完成。

思路

  • 給定的數組 nums是一個排過序的數組,那麼,重複元素一定是在數組中相鄰的元素。也就是說,我們可以通過遍歷數組,找出相鄰相同項,並將其從數組中移除即可
  • 需要原地刪除,那麼我們就不能創建一個副本,而是隻能在原數組上進行操作
    參考:https://blog.csdn.net/qq_30216191/article/details/81348501
  • 特殊情況 數組長度小於等於1,return
  • 遍歷數組,比較當前和下一位
  • 如果相等刪除一位,並把i--,否則會跳過下個元素
  • 遍歷完成,返回數組長度
var removeDuplicates = function(nums) {
  if (nums.length <= 1) {
    return nums.length;
  }
  for (let i = 0; i < nums.length; i++) {
    if (nums[i] === nums[i + 1]) {
      nums.splice(i, 1);
      i--;
    }
  }
  return nums.length;
};
removeDuplicates([1, 1, 2]);

2. 檢查是否存在重複元素(leetcode 217. 存在重複元素)

題目:https://leetcode-cn.com/problems/contains-duplicate/
方法一:對象鍵值法

var containsDuplicate = function(nums) {
    if(nums.length<=1){
        return false;
    }
      let obj = {};//對照對象
  for (var i = 0; i < nums.length; i++) {
    // 判斷當前項是否遍歷過,是則刪除,否存入obj以作對照

    if (obj[nums[i]]) {
      return true
      //數組刪除了一項,要把i回退一下,不然會跳過下一項不去遍歷
    } else {
      obj[nums[i]] = 1;
    }
  }
    return false;
 

    
};

方法二:set法,比較去重數組和原數組的長度

var containsDuplicate = function(nums) {
    if(nums.length<=1){
        return false;
    }
      
    let uniq=[...new Set(nums)];
    return !(uniq.length===nums.length);
 

    
};

3. 檢查相鄰k個元素是否存在重複元素(leetcode 219. 存在重複元素 II)

題目:https://leetcode-cn.com/problems/contains-duplicate-ii/
給定一個整數數組和一個整數 k,判斷數組中是否存在兩個不同的索引 i 和 j,使得 nums [i] = nums [j],並且 i 和 j 的差的絕對值最大爲 k。
對每一個元素,使用includes方法判斷[index+1~index+k+1]的範圍內是否有重複元素

some() 方法會依次執行數組的每個元素: 如果有一個元素滿足條件,則表達式返回true , 剩餘的元素不會再執行檢測。
如果沒有滿足條件的元素,則返回false。
array.some(function(currentValue,index,arr),thisValue)

includes() 方法用來判斷一個數組是否包含一個指定的值,如果是返回 true,否則false。
arr.includes(searchElement, fromIndex)

//是否存在重複元素2
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {boolean}
 */
var containsNearbyDuplicate = function(nums, k) {
//some遍歷得到第一個函數的返回值爲true,就會return true,如果q
  return nums.some((item, index) => {
  
    return nums.slice(index + 1, index + k + 1).includes(item);
  });
};

二、查找數組中的元素

1. leetcode 26. 兩數之和

題目:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和爲目標值的那 兩個 整數,並返回他們的數組下標。
你可以假設每種輸入只會對應一個答案。但是,你不能重複利用這個數組中同樣的元素。
方法一:indexof用法 (慢)

b = nums.indexOf(target - nums[i]);

實際上是對數組再遍歷一次,雖然在寫法上有優化,但是實際時間複雜度還是O(N*N)。
如何快速地在數組中檢索值?使用 indexOf 其實已經在數據中檢索特定值的思路上了。只不過 indexOf 內部還是對數組進行循環檢索,因此並沒有達到更快的要求。在這方面, hash表 可以幫助到我們。
比如我們有一個對象 obj = { …, a: 1} ,當我們取值 Obj.a 時,是個直接尋址的過程,因此效率是很高的。
方法二:使用對象索引(快)
我們創建一個對象,並給它賦值,對象的鍵值是我們想要檢索的值,對象的值是在數組中的索引。nums.forEach((e, i) => mapObj[e] = i);然後遍歷查找對象:mapObj[targer - nums[i]];
方法三:使用map(最快最好)
Map是一組鍵值對的結構,具有極快的查找速度。map的格式:在這裏插入圖片描述

var twoSum = function(nums, target) {
    let map = {};
    if ((nums.length <= 1)) {
        return [];
    }

    let res = [];
    // nums.forEach((e, i) => map.set(e, i));//map.set存放鍵值對

    for (let i = 0; i < nums.length; i++) {
        let num = nums[i];
        /* 不存在時,存入 */
        if (!map[num]) {
            map[num] = i;
        }
        /* 判斷是否有差值存在 */
        let j = map[target - num];
        if (j !== undefined && j !== i) {
            res.push([i, j]);
        }
    }
    

    return res;
};

2.數組中出現次數超過一半的數字(牛客網-劍指 offer)

牛客網-數組中出現次數超過一半的數字
數組中有一個數字出現的次數超過數組長度的一半,請找出這個數字。例如輸入一個長度爲9的數組{1,2,3,2,2,2,5,4,2}。由於數字2在數組中出現了5次,超過數組長度的一半,因此輸出2。如果不存在則輸出0。
思路

  • 特殊情況:長度爲1/0
  • 新建map,遍歷數組,依次儲存數組值和頻率
  • 如果map裏有item這一項,頻率value+1,並判斷是否超過Math.floor(numbers.length / 2),超過則return,
  • 注意需要循環內return,所以必須使用for循環,不能使用foreach
  • 如果map裏沒有item這一項,頻率value爲1
  • 循環結束沒有返回,說明數組不存在這樣的元素
function MoreThanHalfNum_Solution(numbers) {
  // write code here
  if (numbers.length === 0) return 0;
  if (numbers.length === 1) return numbers[0];
  let map = new Map();
  for (let i = 0; i < numbers.length; i++) {
    //map裏有item這一項
    if (map.has(numbers[i])) {
      map.set(numbers[i], map.get(numbers[i]) + 1); //頻率value+1
      if (map.get(numbers[i]) > Math.floor(numbers.length / 2))
        return numbers[i]; //頻率value>一半長度,返回
    }
    //map裏沒有item這一項
    else {
      map.set(numbers[i], 1);
    } //頻率value爲1
  }
  //循環結束沒有返回,說明數組不存在這樣的元素
  return 0;
}
MoreThanHalfNum_Solution([1, 2, 3, 2, 2, 2, 5, 4, 2]);

3. 旋轉數組的最小數字(牛客網-劍指 offer)

題目描述
把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。 輸入一個非減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。 NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20190428170836155.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8yODkwMDMwNw==,size_16,color_FFFFFF,t_70

思路
數組可以被分成兩個不減的子數組,最小值就是第二個子數組的開頭元素,使用二分法尋找這個元素,使用三個指針:左指針,右指針,中間指針

  1. 沒有重複元素的數組,比較mid和right的大小,
    • 如果mid小於right,說明mid-right是單調遞增(這中間不會有最小值),min在left~mid中間;
    • 如果mid大於right,說明mid-right不是單調遞增(mid不會是最小值,但是這中間會有最小值),min在mid+1~right中間;
    • mid=right,說明存在重複元素,不能直接判斷單調性,右指針左移一位,依次比較。

沒有重複元素的數組:
在這裏插入圖片描述
有重複元素的數組:
在這裏插入圖片描述
代碼

function minNumberInRotateArray(rotateArray) {
  // write code here
  // 空數組/單元素數組
  if (!rotateArray || rotateArray.length === 1) {
    return rotateArray[0] || 0;
  }
  let left = 0, //左指針
    right = rotateArray.length - 1; //右指針
  while (left < right) {
    let mid = Math.floor((left + right) / 2);
    //mid和right相等,最小值一定在right元素的右邊
    if (rotateArray[mid] === rotateArray[right]) {
      right--; //右指針左移動一位,依次比較
    }
    //mid-right非遞增,最小值一定在mid元素的右邊
    else if (rotateArray[mid] > rotateArray[right]) {
      left = mid + 1; //左指針移動到mid右邊第一位
    }
    //mid-mid遞增,最小值一定在mid/mid元素的
    else right = mid; //右指針移動到mid
  }
  // left和right相遇退出循環,該位置就是最小值
  return rotateArray[right];
}

三、數組排序

1.打亂數組順序

leetcode 384. Shuffle an Array
打亂數組順序,沒有重複元素
Fisher–Yates shuffle洗牌算法

  • Step1:從數組末尾開始遍歷,選取當前i位置的元素。然後從0-i隨機產生一個位置k,交換a[k]和a[i]
  • Step2:每次遍歷,都只從當前位置前面生成隨機位置,因爲後面的元素已經亂序
  • Math.floor(Math.random() * (arr.length - i ))生成0-i的隨機位置

在這裏插入圖片描述
在這裏插入圖片描述
參考; https://blog.csdn.net/duola8789/article/details/78749917


var Solution = function(nums) {
  this.nums = nums;
};

/**
 * Resets the array to its original configuration and return it.
 * @return {number[]}
 */
Solution.prototype.reset = function() {
  return this.nums;
};

/**
 * Returns a random shuffling of the array.
 * @return {number[]}
 */
Solution.prototype.shuffle = function() {
  //交換數組元素順序
  const swap = (a, i, j) => {
    [a[i], a[j]] = [a[j], a[i]];
  };
  let arr = this.nums.slice(); //深拷貝數組,不然會影響reset的輸出

  for (let i = arr.length - 1; i >= 0; i--) {
     swap(arr, i, Math.floor(Math.random() * (arr.length - i )));
    //swap(arr, i, Math.floor(Math.random() *i ));
  }
  return arr;
};

2.最小的K個數

牛客網劍指offer——數組合集
輸入n個整數,找出其中最小的K個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,。

方法一:sort法
sort正序排序,返回前k個元素:

function GetLeastNumbers_Solution(input, k)
{
    if (input.length < k) return [];
    return input.sort((a,b)=>(a-b)).slice(0,k);
}

方法二:大頂堆法

  • 取前k個元素構建大頂堆
  • 從前向後遍歷k-len元素,
  • 元素大於大頂堆的根,說明他不可能在最小的k個數裏面,跳過這次循環
  • 元素小於大頂堆的根,說明大頂堆的根在最小的k個數裏面,當前元素可能在最小的k個數裏面,交換大頂堆的根和當前元素,並重新維護這個堆

*基於堆排序算法,構建最大堆。時間複雜度爲O(nlogk)
*如果用快速排序,時間複雜度爲O(nlogn)
*如果用冒泡排序,時間複雜度爲O(n*k)

function GetLeastNumbers_Solution(input, k)
{
   // write code here
  if (input.length < k) return [];
  //   let kLeasts = input.slice(0, k - 1);
  buildHeap(input, k); //取前k個元素構建大頂堆
  for (let i = k; i < input.length; i++) {
    if (input[i] > input[0]) continue; //元素大於大頂堆的根,跳過
    swap(input, i, 0); //元素小於大頂堆的根,交換大頂堆的根和當前元素
    headAdjust(input, 0, k); //調整大頂堆
  }
  return input.slice(0, k).sort((a, b) => a - b);//題目要求生序排序
}
function swap(a, i, j) {
  [a[i], a[j]] = [a[j], a[i]];
}
//從輸入節點處調整堆
function headAdjust(arr, cur, len) {
  let childMax = 2 * cur + 1; //指向子樹中較大的位置,初始值爲左子樹的索引

  //子樹存在(索引沒超過數組長度)而且子樹值大於根時,此時不符合大頂堆結構,進入循環,調整堆的結構
  while (childMax < len) {
    //判斷左右子樹大小,如果右子樹更大,而且右子樹存在,childMax指針指向右子樹
    if (arr[childMax] < arr[childMax + 1] && childMax + 1 < len) childMax++;
    //子樹值小於根節點,不需要調整,退出循環
    if (arr[childMax] < arr[cur]) break;
    //子樹值大於根節點,需要調整,先交換根節點和子節點
    swap(arr, childMax, cur);
    cur = childMax; //根節點指針指向子節點,檢查子節點是否滿足大頂堆規則
    childMax = 2 * cur + 1; //子節點指針指向新的子節點
  }
}
// 對arr的前k個元素,建立大頂堆
function buildHeap(arr, k) {
  //從最後一個非葉子節點開始,向前遍歷,
  for (let i = Math.floor(k / 2 - 1); i >= 0; i--) {
    headAdjust(arr, i, k); //對每一個節點都調整堆,使其滿足大頂堆規則
  }
}

3.合併兩個有序數組

leetcode 88. Merge Sorted Array
給定兩個有序整數數組 nums1 和 nums2,將 nums2 合併到 nums1 中,使得 num1 成爲一個有序數組。
思路

  1. 合併數組的長度爲n + m ,從後往前遍歷數組,往數組裏存入兩個數組中的較大的值
  2. 數組1的數被存完以後,開始從將數組2的數組依次存入
var merge = function(nums1, m, nums2, n) {
  //if (m === 0 || n === 0) return [].concat(nums1, nums2);

  let [i, j, index] = [m - 1, n - 1, n + m - 1];
  while (i >= 0 && j >= 0) {
    nums1[i] >= nums2[j]
      ? (nums1[index--] = nums1[i--])
      : (nums1[index--] = nums2[j--]);
  }
  while (j >= 0) {
    nums1[index--] = nums2[j--];
  }
};

4.顏色分類——重複數組排序(leetcode 75. Sort Colors)

leetcode 75. Sort Colors
給定一個包含紅色、白色和藍色,一共 n 個元素的數組,原地對它們進行排序,使得相同顏色的元素相鄰,並按照紅色、白色、藍色順序排列。你能想出一個僅使用常數空間的一趟掃描算法嗎?

方法一:計數法——兩次遍歷
思路

  1. 首先遍歷一遍原數組,分別記錄 0,1,2 的個數。
  2. 然後更新原數組,按個數分別賦上 0,1,2。

方法二:雙指針分區法——一次遍歷
思路

  1. 定義三個指針:low指向0分區的下一個位置mid指向1分區的下一個位置high指向2分區的前一個位置
  2. 如圖所示,0區塊在前,1區塊在中間,2區塊在後,中間的代表尚未遍歷的數字,值不確定。
  3. mid指針遍歷數組
  4. 如果 mid0,交換lowmid的元素,lowmid都下移一位,0分區增加一個元素
  5. 如果 mid1mid下移一位,1分區增加一個元素
  6. 如果 mid2,交換highmid的元素,high向前移動一位,2分區增加一個元素,mid不移動,因爲mid元素還需要再進行下一輪比較,不一定是1分區的元素
    在這裏插入圖片描述
    代碼

var sortColors = function(nums) {
  if (nums.length <= 1) return nums;
  let low = 0,
    i = 0,
    high = nums.length - 1;
  while (i <= high) {
    switch (nums[i]) {
      case 0:
        swap(nums, i++, low++);
        break;
      case 2:
        swap(nums, i, high--);
        break;
      case 1:
        i++;
        break;
    }
  }

  return nums;
};
var swap = function(a, i, j) {
  [a[i], a[j]] = [a[j], a[i]];
};

四、數組子序列

1. 連續子數組的最大和(劍指offer-時間效率)

題目描述,點擊查看原題
輸入一個整型數組,數組裏有正數也有負數。數組中一個或連續的多個整數組成一個子數組。求所有子數組的和的最大值。要求時間複雜度爲O(n)

方法一:枚舉法
思路

  • 枚舉出數組的所有子數組並求出它們的和。一個長度爲n的數組,總共有n(n+1)/2個子數組。
  • 對數組內每一個數A[i]進行遍歷,然後遍歷以它們爲起點的子數組,比較各個子數組的大小,找到最大連續子數組;
  • 計算出所有子數組的和,兩層遍歷,最快也需要O(n2)的時間

方法二:遍歷法
思路

  • 找最大子序列之和,等價於一段找連續的子序列,和是最大值,因爲和爲負的子序列減少和,所以直接拋棄這個子序列和更大
  • 特殊情況:數組爲空/單元素
  • 數組全是負數時,最大和爲數組中的最大值
  • 數組有正數時,從頭到尾逐個累加數組中的每個數字,存放到curSum,如果curSum小於0,拋棄之前的累加值,重新開始計數,curSum=item
  • 比較curSummaxSum,取最大值,存進 maxSum,爲當前歷史序列和的最大值
    在這裏插入圖片描述
function FindGreatestSumOfSubArray(array)
{
    // write code here
     //數組爲空/單元素
  if (array.length === 0) return 0;
  if (array.length === 1) return array[0];
  //全是負數時,最大和爲數組中的最大值
  if(array.every(item => item < 0)) {
      return Math.max(...array);
  }
  //數組有正數時,要遍歷比較最大和
 
    let curSum,
      maxSum = 0;
    array.forEach((item, index) => {
      curSum = curSum > 0 ? curSum + item : item;
      maxSum = Math.max(curSum, maxSum);
    });
    return maxSum;
 
  
}

2. 買賣股票的最佳時機(leetcode 121)

題目描述,點擊查看原題
給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。如果你最多隻允許完成一筆交易(即買入和賣出一支股票),設計一個算法來計算你所能獲取的最大利潤。注意你不能在買入股票前賣出股票。

方法一:O(n)遍歷法

思路

  • 等價於找一個數組的兩個元素子序列,使得他們差值最大,要求小元素在前,大元素在後
  • 遍歷數組,i指向賣出天數
  • maxProfit保存最大利潤,是0~i-1之間的差值的最大值,每次最大值只能在當前元素-當前元素之前的最小買入價以及上次保存的最大利潤中產生。因爲要使用當前元素之前的minPrice,所以先比較更新maxProfit
  • minPrice保存最小買入價,是0~i-1之間的最小值,每次比較當前值上次保存的最小值
  • 遍歷完成以後的 maxProfit就是整個數組中的最大差值
    在這裏插入圖片描述

代碼

var maxProfit = function(prices) {
  if (prices.length <= 1) return 0;
  let minPrice = prices[0], //最小買入價,初始化爲第一個價格
    maxProfit = 0; //最大利潤,初始爲0
  for (let i = 0; i < prices.length; i++) {
    maxProfit = Math.max(maxProfit, prices[i] - minPrice); //和當前價和最小買入價之差比較,更新最大利潤
    minPrice = Math.min(minPrice, prices[i]); //和當前價格比較,更新最小買入價
  }
  return maxProfit;
};

2. 買賣股票的最佳時機2(leetcode 122)

題目描述,點擊查看原題
給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。
設計一個算法來計算你所能獲取的最大利潤。你可以儘可能地完成更多的交易(多次買賣一支股票)。
思路

  • 比較數組相鄰元素,後一位比較大,就把差值累加到結果上

代碼

var maxProfit = function(prices) {
  if (prices.length <= 1) return 0;
  let res=0;
  for (let i = 1; i < prices.length; i++) {
    prices[i] > prices[i - 1] ? (res += prices[i] - prices[i - 1]) : "";
  }
  return res;
};


五、多維數組

1. 構建乘積數組(劍指 offer:數組合集)

題目描述,點擊查看原題
給定一個數組A[0,1,…,n-1],請構建一個數組B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]。不能使用除法。

思路
B[i]的值可以看作下圖的矩陣中每行的乘積。也就是剔除矩陣i行數組中索引爲i的元素以後,其他元素的乘積。
在這裏插入圖片描述

  • 特殊情況: 長度小於等於1,返回自身
  • 新建數組存放結果
  • for循環遍歷矩陣每一行
  • .filter方法剔除矩陣i行數組中,索引爲i的元素
  • .reduce方法將新數組的所有元素連乘
  • 返回值壓入result數組
  • 循環完成,返回數組
function multiply(array) {
  // write code here
  //長度小於等於1,返回自身
  if (array.lenght <= 1) {
    return array;
  }
  //新建數組存放結果
  var result = [];
  //遍歷0~array.length-1,矩陣的第一行到最後一行
  for (let i = 0; i < array.length; i++) {
    //.filter方法剔除矩陣i行數組中,索引爲i的元素
    //.reduce方法將新數組的所有元素連乘
    //返回值壓入result數組
    result.push(
      array
        .filter((item, index) => index != i)
        .reduce((cur, pre) => cur * pre, 1)
    );
  }
  return result;
}
multiply([1, 2, 3]);

2. 二維數組中的查找(劍指 offer:數組合集)

題目描述,點擊查看原題
在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。

思路

  • 定位右上角元素:比它小的元素都在它同行左側,比它大的元素都在它的下面的行
  • while循環:當元素座標在邊界內,進入循環
  • 判斷目標值和座標元素大小關係
  • 相等,查找成功,return
  • 大於,應該在它的下面的行,y座標行數加一,進入下一輪循環
  • 小於,應該在它的同行左側,x座標列數減一,進入下一輪循環
  • 循環結束,return
function Find(target, array) {
  //右上角元素
  var i = array.length - 1;
  var j = 0;

  //當元素座標在邊界內,進入循環
  while (i >= 0 && j < array[i].length) {
    if (target == array[i][j]) {
      //目標值就是座標元素,return
      return true;
    } else if (target > array[i][j]) {
      //目標值大於座標元素,y座標行數加一
      j++;
      continue;
    } else if (target < array[i][j]) {
      //目標值大於座標元素,x座標列數減一
      i--;
      continue;
    }
  }
  return false;
}

六、生成新數組

1. 漢諾塔蓋大樓(2019騰訊春招前端筆試題)

n天蓋完一棟大樓,每天運來一個模塊,面積在這裏插入圖片描述,要求必須最大的模塊先搭,然後搭建面積-1的模塊,依次往上,直到搭建完所有模塊
輸入數據組數,每組數據包含兩個:1.總天數,2,每天運來的模塊的面積組成的數組
要求輸出:n行數據,每一行爲當天搭建的模塊,按順序排列的一個數組;如果當天沒有搭建模塊,則當前數組元素爲empty
在這裏插入圖片描述

/**
 *主程序
 *
 * @param {*} cnt 組數
 * @param {*} cin 輸入
 */
function tower(cnt, cin) {
  let modalGrp = [];
  for (let i = 0; i < cnt; i + 2) {
    //將輸入數據倆倆一組,放入modalGrp數組
    modalGrp[i] = {}; //每組是一個對象
    modalGrp[i].day = cin[i]; //day存放天數
    modalGrp[i].modal = cin[i + 1]; //modal存放每天運來的模塊數組
    getDaliyModal(modalGrp[i]);
  }
/**
 *輸出一組工程的模塊搭建狀況,
 *
 * @param {*} modalGrp 輸入的一組工程數據,一個對象,包含day和modal兩個屬性
 * @returns 返回一個數組,索引代表天數,值代表當天搭建的模塊
 */
function getDaliyModal(modalGrp) {
  if (modalGrp.day <= 1) return modalGrp.modal; //特殊情況,返回自身
  let res = []; //存放輸出
  let max = modalGrp.day; //存放要搜索的模塊裏的最大值,初始值爲modalGrp.day,依次減一
  let map = new Map(); //存放modal面積和索引鍵值對
  modalGrp.modal.forEach((item, index) => {
    map.set(item, index);
  });
  let insertIndex = map.get(max); //初始max的索引,
  while (max > 0) {
    //max小於1,結束循環

    //當前max的索引小於max+1的索引時(max比max+1早拿到)/max是初始值時
    if (map.get(max) < map.get(max + 1) || max === modalGrp.day) {
      res[insertIndex] = res[insertIndex]
        ? res[insertIndex].concat(max)
        : [max]; //在res的初始max的索引位置插入max值
    } else {
      //當前max的索引大於max+1的索引時(max比max+1晚拿到)
      res[map.get(max)] = [max]; //在res的當前max的索引位置插入max值
      insertIndex = map.get(max); //把插入位置更新爲當前最大值的索引
    }

    max--;
  }
  return res;
}
tower(1, [4, [3, 1, 4, 2]]);
// tower(3, [4, [3, 1, 4, 2], 5, [3, 1, 5, 2, 4], 6, [3, 1, 5, 2, 4, 6]]);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章