質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

771閲覧

HashMapを使った配列の比較

macaroni323

総合スコア31

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2021/08/16 23:14

LeetCode で1051. Height Checkerという問題を解いています。

Example 1
Input: heights = [1,1,4,2,1,3]
Output: 3
Explanation:
heights: [1,1,4,2,1,3]
expected: [1,1,1,2,3,4]
Indices 2, 4, and 5 do not match.
Example 2
Input: heights = [5,1,2,3,4]
Output: 5
Explanation:
heights: [5,1,2,3,4]
expected: [1,2,3,4,5]
All indices do not match.
Example3
Input: heights = [1,2,3,4,5]
Output: 0
Explanation:
heights: [1,2,3,4,5]
expected: [1,2,3,4,5]
All indices match.

という風に与えられた配列(Input heights)に対して、その配列が昇順で並べられた時と、元の配列とを比較して値が違う箇所の個数をOutputとして出力しろ、という問題です。

これをArraysortを使わずHashMapで行いたいのですが、いまいちうまく行っておりません。
Twoポインターの使い方が良くないのだと思いますが、どのように書くべきでしょうか。

java

1class Solution { 2 public int heightChecker(int[] heights) { 3 Map<Integer, Integer> map = new HashMap<>(); 4 5 for(int i = 0; i< heights.length; i++){ 6 map.put(heights[i], map.getOrDefault(heights[i], 0) + 1); 7 } 8 9 int result = 0; 10 List keys = new ArrayList(map.keySet()); 11 12 for (int i = 0, curHeight = 0 ; curHeight < heights.length ; curHeight++) { 13 if(map.get((int)keys.get(i)) > 0) { 14 if(heights[curHeight] != (int)keys.get(i)){ 15 result++; 16 } 17 map.put((int)keys.get(i), map.get((int)keys.get(i)) - 1); 18 }else{ 19 i++; 20 } 21 } 22 return result; 23 } 24}

回答例として以下のようなコードがあり、こちらではint[101]を使っているのですが、上記では以下と同じことをHashMapで行いたいと考えております。

java

1class Solution { 2 public int heightChecker(int[] heights) { 3 int[] heightToFreq = new int[101]; 4 5 for (int height : heights) { 6 heightToFreq[height]++; 7 } 8 9 int result = 0; 10 int curHeight = 0; 11 12 for (int i = 0; i < heights.length; i++) { 13 while (heightToFreq[curHeight] == 0) { 14 curHeight++; 15 } 16 17 if (curHeight != heights[i]) { 18 result++; 19 } 20 heightToFreq[curHeight]--; 21 } 22 23 return result; 24 } 25}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

まずどういうアルゴリズムで進めるかをきちんと整理しましょう。
配列のソートをするのが手っ取り早いわけですが、それをせずにするわけですよね。
解答の場合は、ソートの代わりに、
0. 高さごとの度数分布を調べる
0. 低いほうから順に個数を見ていくと、左から順にその高さがその個数分並んでいることになる

とすることで、疑似的にソートをしていることになります。
質問者のコードでは、maisumakunさんの指摘通り、HashMapから得られるkeySetの順序の保証が無いため、
Listに突っ込んだ後に高さ順に並んでいる保証が取れません。

HashMapは、特定の順番で処理をするという目的には向かないので、違うものを使いましょう。
TreeMapが適しているかと思います。
higherEntryなどを駆使すれば、Listに詰めなおす必要もありません。

蛇足
Mapでのカウントは次のように書くとスマートです。

java

1 for(int i = 0; i< heights.length; i++){ 2 map.merge(heights[i], 1, Integer::sum); 3 }

投稿2021/08/17 00:05

swordone

総合スコア20669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

macaroni323

2021/08/20 21:54

ありがとうございました
guest

0

List keys = new ArrayList(map.keySet());としていますが、keysの順序は保証されていないのではないでしょうか?

投稿2021/08/16 23:46

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/08/16 23:48

HashMap.keySetの返り値はSetですが、特段の順序の保証はなさそうです。
macaroni323

2021/08/20 21:54

ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問