오늘 할일
1. LeetCode
오늘 한일
1. LeetCode
public class Solution {
public boolean increasingTriplet(int[] nums) {
for(int i=0; i< nums.length-2; i++){
for(int j=i+1; j<nums.length-1; j++){
for(int k=j+1; k<nums.length; k++){
if(nums[i]<nums[j] && nums[j]<nums[k]){
return true;
} else{
}
}
}
}
return false;
}
}
복잡도 조건을 확인해보니
Could you implement a solution that runs in O(n) time complexity and O(1) space complexity?
시간복잡도 O(n)에 공간복잡도 O(1)로 해결하라고 되어있었다. 추가적인 최적화가 필요해보인다.
최적화 시도
class Solution {
public boolean increasingTriplet(int[] nums) {
int size=nums.length;
Map<Integer, List<Integer>> index_table=new HashMap<>();//value와 indexList
for(int i=0; i<size; i++){
int value=nums[i];
if(!index_table.keySet().contains(value)){//현재 값이 key로 저장되어있지 않다면
List list=new ArrayList<Integer>();//새로운 리스트에
list.add(i);//index정보를 추가해서
index_table.put(value, list);//put
} else{//값이 이미 key로 존재한다면
index_table.get(value).add(i);//인덱스정보 추가
}
}
List<Integer> key_list=index_table.keySet().stream().toList();
for(int i=0; i< key_list.size()-2; i++){
int value1= key_list.get(i);
for(int j=i+1; j< key_list.size()-1; j++) {
int value2 = key_list.get(j);
for(int k=j+1; k<key_list.size(); k++) {
int value3 = key_list.get(k);
List indexes1 = index_table.get(value1);
List indexes2 = index_table.get(value2);
List indexes3 = index_table.get(value3);
int indexes1_max = (int) Collections.max(indexes1);
int indexes2_min = (int) Collections.min(indexes2);
int indexes2_max = (int) Collections.max(indexes2);
int indexes3_min = (int) Collections.min(indexes3);
if (indexes1_max < indexes2_min && indexes2_max < indexes3_min)
return true;
}
}
}
return false;
}
}
그 결과 기존 Time Limit Exceeded에러가 난 test case 32번을 통과하고 62번까지 진행된 것을 확인할 수 있었다.
해당 에러는 value들을 순차적으로 확인하기 이전에, 크기 순서대로 정렬이 되어있지 않아서 임을 확인할 수 있었다. 다음과 같이 sort코드를 추가한 뒤 에러가 발생했던 테스트 코드를 통과했다는 것을 확인했다.
하지만 다른 테스트 케이스에서 오류가 발생했다.
몇가지 조건을 보완한 후 제출해보았는데 Time Limit Exceeded가 다시 발생하였다.
최적화를 추가적으로 진행해야 할 듯 하다.
//74번 케이스를 위한 사전 체크
boolean isDescending=false;
for(int i=0; i<nums.length-1; i++){
if(nums[i]>nums[i+1]) {
isDescending = true;
} else {
isDescending=false;
break;
}
}
if(isDescending)
return false;
가장 오래걸린 문제가 아닐까 싶다. 이번 문제의 풀이는 좀 난잡하게 했기에 전체 알고리즘을 정리해보면 배열 원소를 기준으로 정렬한 다음 해당하는 인덱스들을 비교하는 방식으로 풀이하였다. 구체적인 접근방법은 아래와 같다.
int size=nums.length;
Map<Integer, List<Integer>> index_table=new HashMap<>();//value와 indexList
for(int i=0; i<size; i++){
int value=nums[i];
if(!index_table.keySet().contains(value)){//현재 값이 key로 저장되어있지 않다면
List list=new ArrayList<Integer>();//새로운 리스트에
list.add(i);//index정보를 추가해서
index_table.put(value, list);//put
} else{//값이 이미 key로 존재한다면
index_table.get(value).add(i);//인덱스정보 추가
}
}
//(-3: 6) (-1: 5) (0: 0, 4) (1: 3) (2: 2) (4: 1)
List<Integer> key_list=index_table.keySet().stream().sorted().collect(Collectors.toList());
//74번 케이스를 위한 사전 체크
boolean isDescending=false;
for(int i=0; i<nums.length-1; i++){
if(nums[i]>nums[i+1]) {
isDescending = true;
} else {
isDescending=false;
break;
}
}
if(isDescending)
return false;
//본격 알고리즘
for(int i=0; i< key_list.size()-2; i++){
int value1= key_list.get(i);
for(int j=i+1; j< key_list.size()-1; j++) {
int value2 = key_list.get(j);
for(int k=j+1; k<key_list.size(); k++) {
int value3 = key_list.get(k);
List indexes1 = index_table.get(value1);
List indexes2 = index_table.get(value2);
List indexes3 = index_table.get(value3);
int indexes1_min= (int) Collections.min(indexes1);
int indexes1_max = (int) Collections.max(indexes1);
int indexes2_min = (int) Collections.min(indexes2);
int indexes2_max = (int) Collections.max(indexes2);
int indexes3_min = (int) Collections.min(indexes3);
if (indexes1_max < indexes2_min && indexes2_max < indexes3_min)
return true;
if (indexes1_min < indexes2_min && indexes2_min < indexes3_min)
return true;
if (indexes1_max < indexes2_max && indexes2_max < indexes3_min)
return true;
}
}
}
return false;