N이 40000만 보다 작다라는 조건이 있을 때부터 뭔가 있다고 생각했는데 역시는 역시다.

왠만한 알고리즘 가지고는 시간초과를 막지 못할거 같다. 

계속 생각해 보며 해법을 찾아야겠다. 그래도 코드는 한번 올려본다.


먼저 입력받은 문자를 숫자로 나눠주고 6과 9를 제외한 숫자들이 카운터 될때마다 각 해당 배열의 값을 1증가 시키고 6과 9는 홀수번째로 카운터 될때만 1씩

값을 증가시켜 구한다. 마지막에 Collection에 넣어 정렬 한 후 제일 큰 숫자를 검색해주면 된다.



 for문으로 월별 날짜를 더 해 줄수도 있었지만 이렇게 하는게 더 간단해서 했다.




이번 규칙 단계는 규칙만 찾으면 쉽게 문제를 풀 수 있다고 생각한다. 배열을 사용안해도 간단하게 풀 수 있을 거라 생각하고 문제를 풀었다. 


쉽게 풀 수 있는 문제 였는데 집중을 안하면서 했더니 코드가 이상한대로 가고 있었다..  딴 짓하면서 코딩하면 안되겠다..


Map 컬렉션(Map<K, V>)

  Map 컬렉션은 (key)와 값(value)으로 구성된 객체를 저장하는 구조를 갖는다키는 중복으로 저장할 수 없고 값은 중복으로 저장할 수 있다.(동일한 key로 값을 추가하면 기존 key에 해당하는 값은 제거된다.) 따라서 Map 컬렉션은 (key)로 데이터를 관리한다. Map 컬렉션을 구현하는 대표적인 클래스들은 HashMap, Hashtable, LinkedHashMap, TreeMap 등이 있다. 공통적으로 사용되는 주요 메서드들은 put, get, remove, keySet 등이 있다.



 K와 V는 제네릭으로 K는 key 타입, V는 value 타입을 의미한다K와 V는 기본 자료형(int, double, boolean )은 사용할 수 없고 클래스나 인터페이스 타입만 사용이 가능하다.
 Map에 저장된 값을 가져오기 위해서는 get 메서드로 key 값을 입력하여 하나씩 가져오거나, keySet 및 entrySet 메서드를 이용하여 Set 컬렉션에 key 및 value를 저장하여 반복문을 통해 가져올 수 있다. 해당 내용에 대한 예제는 구현 클래스에서 알아보도록 하겠다.

HashMap

 HashMap은 Map 컬렉션의 대표적인 구현 클래스이다. HashMap을 생성하는 방법은 아래와 같다.



예제를 통해서 HashMap을 사용하는 방법에 대해서 간단히 알아보자.

import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class HashMapEx01 { public static void main(String[] args) { // key는 String 타입으로, value는 Integer 타입으로 지정 Map<String, Integer> hm = new HashMap<String, Integer>(); // put 메서드 이용 key와 value 추가 hm.put("A", 90); hm.put("B", 80); hm.put("C", 80); hm.put("D", 60); // size 메서드 이용 저장된 객체 수 출력 System.out.println("저장된 객체 수 : " + hm.size()); // get 메서드로 특정 key에 해당하는 값 출력 System.out.println("D의 값 : " + hm.get("D")); // 동일한 key로 추가(기존 내용 삭제) hm.put("C", 70); System.out.println("-------------------"); // keySet 메서드 이용 저장된 모든 key 값을 Set 컬렉션에 저장 Set<String> keys = hm.keySet(); // 반복자 생성 Iterator<String> it = keys.iterator(); while (it.hasNext()) { String key = it.next(); // Set의 key 값을 하나씩 key에 대입 int value = hm.get(key); // 해당 key에 해당하는 value 대입 / 오토 언박싱 System.out.println(key + " : " + value); } } }

 설명은 예제의 주석 부분을 참고하면 된다.

Hashtable

 Hashtable은 HashMap과 동일한 사용법을 갖는다. 차이점은 Hashtable은 동기화(synchronization)를 보장한다. 따라서 멀티 스레드에서는 Hashtable을 사용해야 하고, 단일 스레드에서는 HashMap을 사용하는 게 유리하다. Hashtable을 생성하는 방법은 아래와 같다.



 이번에는 Hashtable을 생성하고 entrySet 메서드를 이용하여 데이터를 출력하는 방법을 알아보자.

import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; public class HashtableEx01 { public static void main(String[] args) { Map<String, String> ht = new Hashtable<String, String>(); // key와 value값 저장 ht.put("사과", "Apple"); ht.put("복숭아", "Peach"); ht.put("망고스틴", "Mangosteen"); ht.put("석류", "Poemegranate"); ht.put("딸기", "Strawberries"); // entrySet 메서드 이용 Set 컬렉션에 key와 value 저장 Set<Entry<String, String>> fruits = ht.entrySet(); // 반복자 생성 Iterator<Entry<String, String>> it = fruits.iterator(); while (it.hasNext()) { Entry<String, String> entry = it.next(); String key = entry.getKey(); String value = entry.getValue(); System.out.println(key + " : " + value); } } }





Set

 Set은 List와는 다르게 객체(데이터)를 중복해서 저장할 수 없다. 또한 저장된 객체(데이터)를 인덱스로 관리하지 않기 때문에 저장 순서가 보장되지 않는다. 수학의 집합과 비슷한 내용이다. Set 컬렉션을 구현하는 대표적인 클래스들은 HashSet, TreeSet, LinkedHashSet 등이 있다. Set 컬렉션을 구현하는 클래스들이 공통적으로 사용하는 주요 메소드는 add, iterator, size, remove, clear 등이 있고 내용은 아래의 표와 같다.



 Set은 인덱스로 객체를 관리하지 않기 때문에 데이터를 검색하기 위해서는 iterator() 메서드로 Iterator(반복자)를 생성하고 데이터를 가져와야 한다. 해당 내용에 대해서는 밑의 예제에서 알아보자.

HashSet

 HashSet은 Set 컬렉션을 구현하는 대표적인 클래스이다. 데이터를 중복 저장할 수 없고 순서를 보장하지 않는다. HashSet을 생성하는 방법은 아래와 같다.

Set<E> 객체명 = new HashSet<E>();

 예제를 통해서 HashSet 사용방법에 대해서 알아보자.

import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class HashSetEx01 { public static void main(String[] args) { Set<String> set = new HashSet<String>(); set.add("one"); // 데이터 저장(추가) set.add("two"); set.add("three"); set.add("one"); set.add("two"); set.add("4"); set.add("5"); set.add("six"); System.out.println("저장된 데이터 수 : " + set.size()); // 데이터 수 출력 Iterator<String> it = set.iterator(); // Iterator(반복자) 생성 while (it.hasNext()) { // hasNext() : 데이터가 있으면 true 없으면 false System.out.println(it.next()); // next() : 다음 데이터 리턴 } System.out.println("--------------------"); set.remove("three"); // 데이터 제거 System.out.println("저장된 데이터 수 : " + set.size()); // 저장된 데이터 수 출력 it = set.iterator(); // 반복자 재생성(위의 반복문에서 next 메서드로 데이터를 다 가져왔기 때문에 재생성을 // 해야함) while (it.hasNext()) { System.out.println(it.next()); } System.out.println("--------------------"); } }

 위의 예제를 실행하면 아래와 같은 출력 결과를 갖는다. 데이터의 순서가 보장되지 않고 데이터의 중복을 허용하지 않는 것을 알 수 있다. 또한 데이터를 가져오기 위해서 반복자(iterator)를 이용하였고 설명은 예제의 주석을 참고하면 된다.

 HashSet에 객체를 저장하고 가져오는 방법은 아래와 같다.

import java.util.HashSet; import java.util.Iterator; import java.util.Set; class Member { // Member 클래스 String name; // 필드 String id; public Member(String name, String id) { // 생성자 this.name = name; // 필드값 초기화 this.id = id; } } public class HashSetEx02 { public static void main(String[] args) { Set<Member> set = new HashSet<Member>(); // 제네릭 타입이 Member인 HashSet 생성 set.add(new Member("토니 스타크", "ironman")); // 객체 추가 set.add(new Member("피터 파커", "spierman")); // 객체 추가 Iterator<Member> it = set.iterator(); // 반복자 생성 while (it.hasNext()) { Member mb = it.next(); // set에 저장된 다음 객체의 참조값 저장 System.out.println("아이디 : " + mb.id); // id 출력 System.out.println("이름 : " + mb.name); // name 출력 System.out.println("-----------------"); } } }

 위의 예제는 Member 클래스의 생성자를 통해 필드를 초기화하고 객체를 HashSet에 저장하여 값을 가져오는 방법이다.

import java.util.*; class MemberInfo { private String name; // private 필드 private String id; public String getName() {return name;} // 저장된 name값 리턴 public void setName(String name) {this.name = name;} // name값 설정 public String getId() {return id;} // 저장된 id값 리턴 public void setId(String id) {this.id = id;} // id값 설정 } public class HashSetEx03 { public static void main(String[] args) { MemberInfo mm; // MemberInfo 객체 선언 Set<MemberInfo> set = new HashSet<MemberInfo>(); // HashSet 생성 Scanner sc = new Scanner(System.in); // 스캐너 객체 생성 do { mm = new MemberInfo(); // 반복될때 마다 인스턴스 생성(반복문 외부에서 new 연산자 사용 시 1개의 객체만 저장됨) System.out.println("이름 입력 : "); String name = sc.next(); System.out.println("아이디 입력 : "); String id = sc.next(); mm.setName(name); // 위에서 입력한 name 값 설정 mm.setId(id); // id 값 설정 set.add(mm); // set에 mm객체 저장 System.out.println("계속 Y, 정지 N"); String yn = sc.next(); if (yn.equals("y") || yn.equals("Y")) { continue; // Y나, y 입력시 반복문 계속 } else { break; // 다른값 입력시 반복문 종료 } } while (true); System.out.println("---------------"); Iterator<MemberInfo> it = set.iterator(); // Iterator 생성 while (it.hasNext()) { mm = it.next(); System.out.println("이름 : " + mm.getName()); // getName 메서드 호출(name 값 리턴) System.out.println("아이디 : " + mm.getId()); // getId 메서드 호출(id 값 리턴) System.out.println("----------------"); } } }

 위의 예제는 데이터를 키보드로 입력받아서 객체를 HashSet에 저장하고 Iterator를 통해 저장된 객체를 출력하는 조금 더 응용된 예제이다. 설명은 주석을 참고하면 된다.

TreeSet

 TreeSet도 HashSet과 같이 중복된 데이터를 저장할 수 없고 입력한 순서대로 값을 저장하지 않는다. 차이점은 TreeSet은 기본적으로 오름차순으로 데이터를 정렬한다. 예제를 통해서 알아보자.

import java.util.*; public class TreeSetEx01 { public static void main(String[] args) { Set<Integer> set = new TreeSet<Integer>(); set.add(4); // 데이터 추가 set.add(2); set.add(1); set.add(3); set.add(1); set.add(3); Iterator<Integer> it = set.iterator(); // 반복자 생성 while (it.hasNext()) { System.out.println(it.next()); } System.out.println("----------"); Set<String> ts = new TreeSet<String>(); ts.add("a"); ts.add("c"); ts.add("d"); ts.add("b"); Iterator<String> itr = ts.iterator(); while (itr.hasNext()) { System.out.println(itr.next()); } } }

 위의 예제를 실행하면 중복을 허용하지 않고 오름차순으로 데이터를 저장하는 것을 알 수 있다.

LinkedHashSet

LinkedHashSet도 중복된 데이터를 저장할 수 없다. 차이점은 입력된 순서대로 데이터를 관리한다. 

import java.util.*; public class LinkedHashSetEx01 { public static void main(String[] args) { Set<String> set = new LinkedHashSet<String>(); set.add("1"); set.add("1"); set.add("two"); set.add("3"); set.add("4"); set.add("five"); Iterator<String> it = set.iterator(); while (it.hasNext()) { System.out.println(it.next()); } System.out.println("--------------------------"); LinkedHashSet<Integer> lh = new LinkedHashSet<Integer>(); lh.add(1); lh.add(1); lh.add(4); lh.add(2); lh.add(3); Iterator<Integer> it2 = lh.iterator(); while (it2.hasNext()) { System.out.println(it2.next()); } } }

 예제를 실행하면 중복된 데이터는 제외되고 입력된 순서로 값을 출력하게 된다.




입력받은 문자를 배열에 넣고 표에 입력된 값들을 아스키값으로 비교해 맞는 것이 있으면 cnt를 1증가 시켜주고 i값을 1번이나 2번 띄어넘는다. 비교값이 중복되는 것은 같이 묶어주면 되는데 다하고 나서 알아서 안고쳤다.


다음은 코드이다.



먼저 문자열을 입력받고 charAt메소드로 문자들을 아스키코드값으로 나눠 준다. 그 후 대문자 아스키코드 값 A~Z, 즉 65~90 까지의 값들을 for문으로 

그 알파벳들에 맞는 시간들을 배열에 넣는다. 



문자를 아스키코드 값으로 하나하나 나눠준후 값들을 반전시켜 비교한다. 


+ Recent posts