public class Practice1 {
public static String solution(String s) {
if (s == null || s.length() == 0) {
return null;
}
int p1 = 0;
int p2 = s.length() - 1;
while (p1 < p2 && s.charAt(p1) == s.charAt(p2)) {
char c = s.charAt(p2);
while (p1 <= p2 && s.charAt(p1) == c) {
p1++;
}
while (p1 <= p2 && s.charAt(p2) == c) {
p2--;
}
}
return s.substring(p1, p2 + 1);
}
public static void main(String[] args) {
// Test code
System.out.println(solution("ab")); // ab
System.out.println(solution("aaabbaa")); //
System.out.println(solution("aabcddba")); // cdd
}
}
입력 검사
-문자열 s가 null 이거나 길이가 0인 경우 null을 반환
양 끝에서부터 비교
-문자열의 양 끝에서부터 시작하여 같은 문자를 찾음. p1은 문자열의 시작부터, p2는 문자열의 끝부터 시작
문자 비교 및 제거
while (p1 < p2 && s.charAt(p1) == s.charAt(p2))
-p1 과 p2가 가리키는 문자가 같은동안 반복
char c = s.charAt(p2);
-현재 검사하는 문자를 c에 저장
while (p1 <= p2 && s.charAt(p1) == c) {
p1++;
}
p1 이 가리키는 문자가 c와 같은동안 p1을 증가시킴. 이 과정에서 문자열의 왼쪽에서 같은 문자를 제거
while (p1 <= p2 && s.charAt(p2) == c) {
p2--;
}
p2 가 가리키는 문자가 c와 같은동안 p2를 감소시킴. 이 과정에서 문자열의 오른쪽에서 같은 문자를 제거
import java.util.Arrays;
import java.util.HashSet;
public class Practice2 {
public static int[] solution(int[] nums1, int[] nums2) {
HashSet <Integer> set = new HashSet<>();
Arrays.sort(nums1);
Arrays.sort(nums2);
int p1 = 0;
int p2 = 0;
while (p1 < nums1.length && p2 < nums2.length) {
if (nums1[p1] < nums2[p2]) {
p1++;
} else if (nums1[p1] > nums2[p2]) {
p2++;
} else {
set.add(nums1[p1]);
p1++;
p2++;
}
}
int[] result = new int[set.size()];
int idx = 0;
for (Integer i : set) {
result[idx++] = i;
}
return result;
}
public static void main(String[] args) {
// Test code
int[] nums1 = {1, 2, 2, 1};
int[] nums2 = {2, 2};
System.out.println(Arrays.toString(solution(nums1, nums2)));
nums1 = new int[]{4, 9, 5};
nums2 = new int[]{9, 4, 9, 8, 4};
System.out.println(Arrays.toString(solution(nums1, nums2)));
nums1 = new int[]{1, 7, 4, 9};
nums2 = new int[]{7, 9};
System.out.println(Arrays.toString(solution(nums1, nums2)));
}
}
HashSet 선언
-HashSet<Integer> set 은 중복된 값을 저장하기 위한 자료구조. HastSet은 중복을 허용하지 않고 순서를 보장하지 않는 특성을 가짐
배열 정렬
-Arrays.sort(nums1) 과 Arrays.sort(nums2) 를 통해 각 배열을 정렬. 이는 이후 중복된 값 비교를 용이하게 함
두 배열 순회
-p1 과 p2 인덱스를 사용하여 두 배열을 순회
-nums1[p1] < nums2[p2] 일 경우 p1을 증가시켜 다음 원소로 이동
-nums1[p1] > nums2[p2] 일 경우 p2를 증가시켜 다음 원소로 이동
-nums1[p1] == nums[p2] 일 경우 두 배열에서 같은 원소를 발견했으므로 해당 원소를 HashSet에 추가하고 p1과 p2를 모두 증가시켜 다음 원소로 이동
결과 배열 생성
-HashSet에 저장된 값을 result 배열로 옮김
-HashSet은 중복을 허용하지 않기 때문에 중복된 값은 자동으로 제거
-result 배열의 크기는 HashSet의 크기와 같음
-HashSet 의 모든 값들을 result 배열로 옮기면서 인덱스 idx를 증가
public class Practice3 {
public static String solution(String s) {
if (s == null) {
return null;
}
if (s.length() < 2) {
return s;
}
s = removeSpaces(s);
char[] cArr = s.toCharArray();
reverseString(cArr, 0, s.length() - 1);
reverseWords(cArr, s.length());
return new String(cArr);
}
public static String removeSpaces(String s) {
int p1 = 0;
int p2 = 0;
char[] cArr = s.toCharArray();
int length = s.length();
while (p2 < length) {
while (p2 < length && cArr[p2] == ' ') {
p2++;
}
while (p2 < length && cArr[p2] != ' ') {
cArr[p1++] = cArr[p2++];
}
while (p2 < length && cArr[p2] == ' ') {
p2++;
}
if (p2 < length) {
cArr[p1++] = ' ';
}
}
return new String(cArr).substring(0, p1);
}
public static void reverseString(char[] cArr, int i, int j) {
while (i < j) {
char tmp = cArr[i];
cArr[i++] = cArr[j];
cArr[j--] = tmp;
}
}
public static void reverseWords(char[] cArr, int length) {
int p1 = 0;
int p2 = 0;
while (p1 < length) {
while (p1 < p2 || p1 < length && cArr[p1] == ' ') {
p1++;
}
while (p2 < p1 || p2 < length && cArr[p2] != ' ') {
p2++;
}
reverseString(cArr, p1, p2 - 1);
}
}
public static void main(String[] args) {
// Test code
System.out.println(solution("the sky is blue"));
System.out.println(solution(" hello java "));
}
}
pulbic static String removeSpaces(String s) {
int p1 = 0;
int p2 = 0;
char[] cArr = s.toCharArr();
int length = s.length();
while(p2 < length) {
// 공백을 스킵
while (p2 < length && cArr[p2] = ' ') {
p2++;
}
// 단어를 복사
while (p2 < length && cArr[p2] != ' ') {
cArr[p1++] = cArr[p2++];
}
// 다음 공백 이전에 공백 추가
while (p2 < length && cArr[p2] == ' ') {
p2++;
}
if (p2 < length) {
cArr[p1++] = ' ';
}
}
return new String(cArr).substring(0, p1);
}
-removeSpaces 메서드는 문자열 s를 받아 공백을 제거한 새로운 문자열을 반환
-cArr 배열은 입력 문자열 s를 문자 배열로 변환한 것
-p1과 p2는 포인터 변수로, p1은 결과 문자열에 쓰일 인덱스를, p2는 입력 문자열을 탐색하는 인덱스를 나타냄
-첫번째 while 루프는 입력 문자열에서 공백을 스킵
-두번째 while 루프는 공백이 아닌 단어를 복사
-세번째 while 루프는 다시 공백을 스킵
-공백을 추가하는 부분은 마지막 단어 이후의 공백을 처리하기 위함
-최종적으로 new String(cArr).subString(0, p1) 을 통해 결과 문자열을 만들어 반환
public static void reverseString(char[] cArr, int i, int j) {
while (i < j) {
char tmp = cArr[i];
cArr[i++] = cArr[j];
cArr[j--] = tmp;
}
}
-reverseString 메서드는 문자 배열 cArr에서 인덱스 i 부터 j 까지의 문자를 역순으로 뒤집음
-i는 시작 인덱스 j는 끝 인덱스를 나타냄
public static void reverseWords(char[] cArr, int length) {
int p1 = 0;
int p2 = 0;
while (p1 < length) {
while (p1 < p2 || p1 < length && cArr[p1] == ' ') {
p1++;
}
while (p2 < p1 || p2 < length && cArr[p2] != ' ') {
p2++;
}
reverseString(cArr, p1, p2 - 1);
}
}
-reverseWords 메서드는 문자 배열 cArr에서 단어들을 뒤집음
-p1과 p2는 단어의 시작과 끝 인덱스를 나타내며, 공백을 건너뛰는데 사용됨
-첫번째 while 루프는 공백을 스킵하고, 두번째 while 루프는 단어를 찾음
-reverseString 메서드를 호출하여 단어를 뒤집음
public static String solution(String s) {
if (s == null) {
return null;
}
if (s.length() < 2) {
return s;
}
s = removeSpaces(s);
char[] cArr = s.toCharArray();
reverseString(cArr, 0, s.length() - 1);
reverseWords(cArr, s.length());
return new String(cArr);
}
-solution 메서드는 입력 문자열 s 를 받아서 공백을 제거하고 단어들을 뒤집은 결과를 반환
-입력 문자열이 null이면 null을 반환하고, 길이가 1 이하이면 그대로 반환
-removeSpaces 메서드를 통해 공백을 제거한 문자열을 얻고, 이를 문자 배열로 변환하여 단어들을 뒤집고 다시 조합
import java.util.ArrayList;
import java.util.Arrays;
public class Practice4 {
public static ArrayList<ArrayList<Integer>> solution(int[] nums) {
Arrays.sort(nums);
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i == 0 || i > 0 && nums[i] != nums[i - 1]) {
int p1 = i + 1;
int p2 = nums.length - 1;
int sum = 0 - nums[i];
while (p1 < p2) {
if (nums[p1] + nums[p2] == sum) {
result.add(new ArrayList<>(Arrays.asList(nums[i], nums[p1], nums[p2])));
while (p1 < p2 && nums[p1] == nums[p1 + 1]) {
p1++;
}
while (p1 < p2 && nums[p2] == nums[p2 - 1]) {
p2--;
}
p1++;
p2--;
} else if (nums[p1] + nums[p2] < sum) {
p1++;
} else {
p2--;
}
}
}
}
return result;
}
public static void main(String[] args) {
// Test code
int[] nums = {-1, 0, 1, 2, -1, -4}; // [[-1, -1, 2], [-1, 0, 1]]
System.out.println(solution(nums));
nums = new int[] {1, -7, 6, 3, 5, 2}; // [[-7, 1, 6], [-7, 2, 5]]
System.out.println(solution(nums));
}
}
public static ArrayList<ArrayList<Integer>> solution(int[] nums) {
Arrays.sort(nums);
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i == 0 || i > 0 && nums[i] != nums[i - 1]) {
int p1 = i + 1;
int p2 = nums.length - 1;
int sum = 0 - nums[i];
while (p1 < p2) {
if (nums[p1] + nums[p2] == sum) {
result.add(new ArrayList<>(Arrays.asList(nums[i], nums[p1], nums[p2])));
while (p1 < p2 && nums[p1] == nums[p1 + 1]) {
p1++;
}
while (p1 < p2 && nums[p2] == nums[p2 - 1]) {
p2--;
}
p1++;
p2--;
} else if (nums[p1] + nums[p2] < sum) {
p1++;
} else {
p2--;
}
}
}
}
return result;
}
2.세 수의 합이 0이되는 조합 찾기
-for 루프에서 i는 배열을 순회하며 첫 번째 수로 사용될 인덱스를 나타냄.
nums.length - 2 까지만 반복하는 이유는 마지막 두 개의 수는 이미 앞서 검사된 경우이기 때문
-if (i == 0 || i > 0 && nums[i] != nums[i - 1]) 중복된 숫자를 처리하기 위해 이전 값과 비교하여 같지 않은 경우에만 처리
투 포인터 사용
-p1과 p2는 각각 두 번째와 세 번째 수의 인덱스를 가리키며, 처음에는 첫 번째 수의 다음과 마지막 수를 가리킴
-while (p1 < p2) 루프에서 두 번째 수 nums[p1] 과 세번째 수 nums[p2]의 합을 계산
-nums[p1] + nums[p2] == sum 인 경우에는 세 수의 합이 0이 되므로 결과 리스트 result에 추가
-중복된 값은 건너뛰기 위해 while 루프로 중복을 제거
-nums[p1] + nums[p2] < sum 인 경우 p1을 증가시켜 합을 크게 만들고, 반대로 p2를 감소시켜 합을 작게 만듬
결과반환
-모든 경우의 수를 찾은 후에 result 리스트를 반환