iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0
自我挑戰組

30天演算法解題系列 第 16

Day 16:class photo

  • 分享至 

  • xImage
  •  

problem

題目的情境是,要為一個班級拍合照,全班人數必為偶數 (代表至少兩個人),一半的人穿紅衣服,另一半的人穿藍衣服。將全部的人排成兩橫排拍照,規則是:

  • 紅衣服的人在同一排
  • 藍衣服的人在同一排
  • 後排的每個人都要比站他正前方的人高

輸入為兩個元素皆為正整數的陣列,分別包含所有紅衣同學的身高和所有藍衣同學的身高,回傳這個班級是否有辦法拍出符合上述規則的合照。

sample input:
redHeights = [5, 8, 1, 3, 4]
blueHeights = [6, 9, 2, 4, 5]

sample output:
true

第一個想法是,如果紅、藍要各站一排,那麼兩種顏色中有最高身高的一定是後排。以上方範例輸入來說,blueHeights 中有最高身高 9,則藍衣服必須為後排,否則不會有人比 9 還高,也就是沒有人可以站在 9 後面。

決定了前後排以後,接下來就從兩組人中最高的人開始看符不符合後排高於前排的規則,例如紅色最高 8,藍色最高 9,可以符合規則。之所以要從最高的開始是因為最高的前排最難找到比他高的人,如果連最高的後排都不比他高,整體當然也就無法符合規則。

排完了最高的人後,接下來其實是規模較小但一模一樣的問題,所以可以從剩下的人中最高的重複步驟,直到排完所有的人得到最終結果。以程式碼來說,作法就是先由大到小排序兩個陣列,決定前後排後,將元素逐一進行比較。

n 為輸入陣列長度,
time: O(nlogn)
space: O(1)

function classPhotos(redHeights, blueHeights) {
  redHeights.sort((a, b) => b - a);
  blueHeights.sort((a, b) => b - a);

  const firstRowColor = redHeights[0] < blueHeights[0] ? 'red' : 'blue';
  for (let idx = 0; idx < redHeights.length; idx++) {
    const redHeight = redHeights[idx];
    const blueHeight = blueHeights[idx];

    if (firstRowColor === 'red') {
      if (redHeight >= blueHeight) return false;
    } else if (blueHeight >= redHeight) return false;
  }
  return true;
}

上一篇
Day 15:minimum waiting time
下一篇
Day 17:generate document
系列文
30天演算法解題30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
shan33
iT邦新手 2 級 ‧ 2022-09-30 21:18:58

把解題思維寫得很清楚明瞭,好讚

不過金魚腦如我,瞬間眼花看錯 else if 是對到哪一組 if

if (firstRowColor === 'red') {
  if (redHeight >= blueHeight) return false;
} else if (blueHeight >= redHeight) return false;

巢狀if 也許也可以換成兩段 if

if (firstRowColor === 'red' && redHeight >= blueHeight) return false;
if (firstRowColor === 'blue' && blueHeight >= redHeight) return false;

但沒有省到字數...

ramenkun iT邦新手 3 級 ‧ 2022-10-01 12:35:25 檢舉

同意! 當初看到那樣的寫法先記下來,現在回頭看確實有點眼花。內外層對齊加上省略,很容易誤解為同一層級。
我覺得把 firstRowColor === 'blue' 明寫出來並列是很清楚的表達,感謝協助突破盲點。

我要留言

立即登入留言