어느 공원 놀이터에는 시소가 하나 설치되어 있습니다. 이 시소는 중심으로부터 2(m), 3(m), 4(m) 거리의 지점에 좌석이 하나씩 있습니다. 이 시소를 두 명이 마주 보고 탄다고 할 때, 시소가 평형인 상태에서 각각에 의해 시소에 걸리는 토크의 크기가 서로 상쇄되어 완전한 균형을 이룰 수 있다면 그 두 사람을 시소 짝꿍이라고 합니다. 즉, 탑승한 사람의 무게와 시소 축과 좌석 간의 거리의 곱이 양쪽 다 같다면 시소 짝꿍이라고 할 수 있습니다. 사람들의 몸무게 목록 weights이 주어질 때, 시소 짝꿍이 몇 쌍 존재하는지 구하여 return 하도록 solution 함수를 완성해주세요.
제한 사항
2 ≤ weights의 길이 ≤ 100,000
100 ≤ weights[i] ≤ 1,000
몸무게 단위는 N(뉴턴)으로 주어집니다.
몸무게는 모두 정수입니다.
입출력 예
weights
result
[100,180,360,100,270]
4
문제 이해)
- 시소는 중심으로부터 2, 3, 4 거리의 지점에 좌석이 하나씩 있음.
- weights의 길이가 100,000 이기 때문에 시간 복잡도 고려해야 함.
import java.util.*;
class Solution {
public long solution(int[] weights) {
long answer = 0;
Arrays.sort(weights);
Map<Double, Integer> map = new HashMap<>();
for(int i : weights){
double a = i * 1.0;
double b = (i * 2.0) / 3.0;
double c = (i * 1.0) / 2.0;
double d = (i * 3.0) / 4.0;
if(map.containsKey(a)) answer += map.get(a);
if(map.containsKey(b)) answer += map.get(b);
if(map.containsKey(c)) answer += map.get(c);
if(map.containsKey(d)) answer += map.get(d);
map.put((i * 1.0), map.getOrDefault((i * 1.0), 0) + 1);
}
return answer;
}
}
- weights 정렬하였기 때문에 키값은 크거나 같을 수 밖에 없음. 그래서 [1.0], [2.0/3.0], [2.0/4.0 -> 1.0/2.0], [3.0/4.0] 으로 거리 고려하면 됨.
개발자 도구를 사용해 필요한 부분만 찾는다. 뉴스를 부분만 원하기 때문에 뉴스만 해당하는 부분을 클릭해서 해당 태그를 찾는다. class부분에 해당하는 list_body newflash_body를 복사한다.
지금까지 한 부분을 코딩해 보면 아래와 같다.
String url = "https://news.naver.com/main/list.naver?mode=LS2D&sid2=237&sid1=103&mid=shm&date=20230119&page=1";
Document doc = Jsoup.connect(url).get(); //Jsoup에 있는 connect 메소드를 호출하는데 파라미터로 주소 url의 전체 내용을 가져와 document에 저장
Elements elements = doc.getElementsByAttributeValue("class", "list_body newsflash_body"); //class에 해당하는 값을 가지는 모든 tag를 받아야 됨
이런 식으로 위에 클래스 태그에 해당하는 모든 정보들이 나온다.
2. 필요한 태그 분석
위의 태그들을 분석하면 기사 URL, 이미지 URL, 기사 제목, 한 줄 기사 내용이 있다. 더 분석하면 <a>에 기사 제목이 포함되어 있고 <img> 태그에도 기사 제목이 포함되어 있다. 때문에 필요한 정보가 모두 들어가 있는 class = "photo"에 해당하는 속성값의 정보들을 가져올 것이다.
Element element = elements.get(0); //Elements는 여러 개라는 전제가 포함되기 때문에 elements에 데이터가 하나만 달라고 요청
Elements photoElements = element.getElementsByAttributeValue("class", "photo"); //class 속성에 속성값 photo에 해당하는 정보를 가져옴
Element articleElement = photoElements.get(0); //phtoElements에 해당하는 기사 하나 가져옴
Element aElements = articleElement.select("a").get(0); //a태그 하나만 가져옴
photo 값에 해당하는 정보 출력
기사 URL이 적혀있는 href를 속성값을 가져오기 위해 attr을 사용한다.
String articleUrl = aElement.attr("href"); //attr을 사용해 원하는 속성 키를 넣어 값을 가져옴
기사 링크
같은 방식으로 이미지 URL, 제목을 가져오기 때문에 설명에서는 생략하겠다. (밑에 전체 코드 있으니 참고)
* 제목은 img 태그에 포함된 있기 때문에 이미지 속성을 가져오는 부분 활용. *
(2-1) 기사 내용은 다른 페이지에 있기 때문에 기사 주소를 클릭해서 다시 한번 크롤링을 해야 한다.
Document subDoc = Jsoup.connect(articleUrl).get();
Element contentElement = subDoc.getElementById("dic_area"); //기사 내용이 포함된 id
Sring content = contentElement.text();
- text()는 태그 안에 있는 내용만을 가져온다.
- id는 유일한 값이 때문에 중복이 없다. 그래서 get()을 이용해 하나만 가져올 필요가 없다.
3. 전체 소스 코드
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class News {
public static void main(String[] args) throws IOException{
int page = 3;
for(int j = 0; j < page; j++) {
String url = "https://news.naver.com/main/list.naver?mode=LS2D&sid2=237&sid1=103&mid=shm&date=20230119&page="+j;
Document doc = Jsoup.connect(url).get(); //Jsoup에 있는 connect 메소드를 호출하는데 파라미터로 주소 url의 전체 내용을 가져와 document에 저장
Elements elements = doc.getElementsByAttributeValue("class", "list_body newsflash_body"); //class에 해당하는 값을 가지는 모든 tag를 받아야 됨
Element element = elements.get(0); //Elements는 여러개라는 전제이기 때문에 elements에 데이터가 하나만 달라고 요청, (첫번쨰 거 요청)
Elements photoElements = element.getElementsByAttributeValue("class", "photo");
for(int i = 0; i < photoElements.size(); i++) {
Element articleElement = photoElements.get(i); //photoElements에 해당하는 기사 하나씩 가져옴
Elements aElements = articleElement.select("a"); //a 태그를 가져옴
Element aElement = aElements.get(0);
String articleUrl = aElement.attr("href"); //attr에 원하는 속성의 키를 넣으면 값을 줌 -> 기사 링크
Element imgElement = aElement.select("img").get(0); //img 태그에 해당하는 하나 가져옴
String imgUrl = imgElement.attr("src"); //이미지 url
String title = imgElement.attr("alt"); //기사 제목
System.out.println(articleUrl);
System.out.println(imgUrl);
System.out.println(title);
/* 기사 내용
Document subDoc = Jsoup.connect(articleUrl).get();
Element contentElement = subDoc.getElementById("dic_area"); //기사 내용에 포함된 id
String content = contentElement.text(); //text() 태그 안에 값만 나옴 -> <br>이란 거 없이 기사 내용만 나옴
System.out.println(contentElement.text());
*/
}
System.out.println(j+1 + "page 크롤링 종료");
System.out.println();
}
}
}