ys memos

Blog

LeetCode838 Push Dominoesの解答例・解説


leetcode

2021/07/23


並べられているドミノの初期値が与えられ,これらが最終的にどのような形に落ち着くのかを算出する問題

各ドミノの状態は,L,R,.の3種類で,それぞれ左に傾いている,右に傾いている,直立しているを表し,直立しているドミノが右から押されたら左に,左から押されたら右に傾く.また,左右から押された場合は直立を維持し,状態は変化しない.


まずは傾いているドミノの番号と状態をキューqにプッシュ.

キューに格納されている各ドミノが影響を及ぼすドミノをcommandsにインサート. その時,一つのドミノを左右から押す場合は,commandsから削除する.

以上を繰り返す.


main.cpp
class Solution {
public:
  string pushDominoes(string dominoes) {
    queue<pair<int, char>> q; // <idx, /[L|R]/>
    map<int, char> commands; // <idx, /[L|R]/>
    for (size_t i=0; i<dominoes.length(); ++i) {
      if (dominoes[i] != '.') {
        q.emplace(i, dominoes[i]);
      }
    }
    while (!q.empty()) {
      while (!q.empty()) {
        size_t idx = q.front().first;
        if (q.front().second == 'L') {
          idx --;
          if (idx == -1) {
            q.pop();
            continue;
          }
        } else {
          /* q.front().second == 'R' */
          idx ++;
          if (idx == dominoes.length()) {
            q.pop();
            continue;
          }
        }

        if (dominoes[idx] == '.') {
          decltype(commands)::iterator found = commands.find(idx);
          if (found == commands.end()) {
            commands.emplace(idx, q.front().second);
          } else {
            commands.erase(found);
          }
        }

        q.pop();
      }

      for (const auto& command: commands) {
        dominoes[command.first] = command.second;
        q.emplace(command);
      }
      commands.clear();
    }
    return dominoes;
  }
};


戻り値は,ドミノの最終的な状態.

string pushDominoes(string dominoes) {

qは,未処理のドミノを格納するキュー.

commandsは,各ドミノが影響を与えるドミノを格納するハッシュテーブル.

pair<int,char>は,要素番号および状態(L,R)を意味する.

qには,初期値として,初期状態で傾いているドミノを準備する.

	queue<pair<int, char>> q; // <idx, /[L|R]/>
	map<int, char> commands; // <idx, /[L|R]/>
	for (size_t i=0; i<dominoes.length(); ++i) {
		if (dominoes[i] != '.') {
			q.emplace(i, dominoes[i]);
		}
	}

すべてのドミノが処理済みとなるまでループする.

	while (!q.empty()) {

qの先頭から順に,左端のLおよび右端のRは無視しながらループ.

		while (!q.empty()) {
			size_t idx = q.front().first;
			if (q.front().second == 'L') {
				idx --;
				if (idx == -1) {
					q.pop();
					continue;
				}
			} else {
				/* q.front().second == 'R' */
				idx ++;
				if (idx == dominoes.length()) {
					q.pop();
					continue;
				}
			}

Lの場合は左に,Rの場合は右に影響を及ぼすため,その情報をcommandsに保存.

この時,左右から押される場合はcommandsから削除する.

			if (dominoes[idx] == '.') {
				decltype(commands)::iterator found = commands.find(idx);
				if (found == commands.end()) {
					commands.emplace(idx, q.front().second);
				} else {
					commands.erase(found);
				}
			}

qをポップして次のドミノを先頭にする.

			q.pop();
		}

commandsを使って,ドミノの状態を書き換える.

		for (const auto& command: commands) {
			dominoes[command.first] = command.second;
			q.emplace(command);
		}
		commands.clear();
	}

	return dominoes;
}

なんか他の人のソリューションのほうがパフォーマンスが良いので悲しい.


関連タグを探す