String - [Java]

노력하는 배짱이·2021년 3월 31일
0

String

개념

  1. chartAt(int index) : 문자열의 위치에 해당하는 문자를 반환
    ex) String s = "HELLO" -> s.charAt(0) : 'H'

  2. chatAt(int index) - '0' : int 값으로 반환
    ex) String s = "123" -> s.charAt(0) - '0' : 1 (int)

  3. toCharArray() : char[] 반환
    ex) String s = "hello" -> s.toCharArray() : 'h','e','l','l','o' (char[] 배열)

  4. IndexOf(String str) : 해당 문자열의 시작 인덱스 반환
    subString(int biginIndex, int endIndex) : biginIndex 부터 endIndex -1 까지의 문자열을 가져옴
    ex) String s = "test"
    s.indexOf("es") : 1 ("es"의 시작 위치 1를 반환, 없으면 -1 반환)
    s.substring(0,4) : "test" (인덱스가 0 ~ 3 까지의 문자열 반환)

  5. Palindrome : 단어의 가운데 기준으로 양쪽이 같아야 함
    ex) banana => anana

문제

1. charAt()

문제)
문자열로 주어진 음이 아닌 정수값 num1, num2의 합을 문자열로 반환

조건)
num1, num2 < 1000
num1, num2 는 숫자만 포함하며 선행 0을 포함하지 않음

Input : 236 , 777
Output : 1013

풀이

Integer.parseInt()를 이용하지 않고 chartAt()을 이용

  1. num1, num2의 길이를 구하기
  2. while문을 길의가 0이상일 때까지 돌리기
  3. while문 내에서 charAt() - '0'을 이용하여 마지막 수부터 계산하기
  4. carry변수를 이용하여 넘어가는 수 구하기
  5. StringBuilder를 이용하여 수를 입력하고 마지막에 reverse()하여 출력

소스

public class Q1 {

	public static void main(String[] args) {
		String num1 = "236";
		String num2 = "777";
		
		// 결과 : 1013
		System.out.println(solve(num1, num2));

	}

	public static String solve(String num1, String num2) {
		int carry = 0;
		StringBuilder sb = new StringBuilder();

		int num1Length = num1.length() - 1;
		int num2Length = num2.length() - 1;

		while (num1Length >= 0 || num2Length >= 0) {
			int n1 = 0, n2 = 0;
			if (num1Length >= 0) {
				n1 = num1.charAt(num1Length) - '0';
			}

			if (num2Length >= 0) {
				n2 = num2.charAt(num2Length) - '0';
			}

			int sum = n1 + n2 + carry;

			carry = sum / 10;
			sb.append(sum % 10);

			num1Length--;
			num2Length--;
		}

		if (carry != 0) {
			sb.append(carry);
		}

		return sb.reverse().toString();
	}

}

2. toCharArray()

문제)
최소 괄호의 수를 제거하여 '(', ')' 처럼 유효한 parentheses(괄호) string 을 반환
-> 빈 문자열이거나 소문자 만 포함

1)
Input : String s = "in(f(lea)r)n)"
Output : "in(f(lea)r)n"

2)
Input : String s = "))(("
Output : ""

3)
Input : String s = ")()("
Output : "()"

풀이

  1. toCharArray를 이용하여 char[]로 받는다.
  2. char[]에서 하나의 문자를 빼면서 비교 저장한다.
  3. openBrace( '('의 갯수 ) 를 기중으로 잡아서 계산
  4. 역순으로 저장하면서 openBrace 갯수 만큼 제외하고 저장한다.

예를들어 "in(f(lea)r)n)" 이 주어졌을 때 여는 괄호는 2개 닫는 괄호는 3개가 나온다. 그러면 첫번째 닫는 괄호, 두번째 닫는 괄호, 세번째 닫는 괄호 중 하나를 없애면 정상적인 괄호 문자열이 된다.

하지만 "))((" 경우에는 닫는 괄호가 먼저 나오기 때문에 openBrace의 값이 영향을 받지 않는다. 즉 openBrace == 0 일 때는 닫는 괄호를 신경쓰지 않아도 된다.

만일 ")()(" 이면 첫 번째 닫는 괄호는 무시하고 그 다음 여는 괄호부터 시작하면 되는 것이다.

정리하자면 여는 괄호 '('의 개수를 파악하여 openBrace를 구한다. 그 뒤에 역순으로 문자를 저장하면서 '(' 이면서 openBrace가 0이 아닐때까지 제외하면 된다.

역순으로 저장하는 이유는 ")()("와 같은 경우가 있기 때문이다. 처음에 나오는 닫는 괄호는 무시하면 "()("이 남는다. 이때 openBrace = 1이다. 앞서 말한 조건을 적용하여 앞에서부터 처리를 하게 되면 ")(" 이와 같이 남게 되어 잘못된 결과를 도출하게 된다. 그래서 이때 역순으로 처리하면 마지막에 있는 여는 괄호는 무시하고 ")("가 저장이 되고 이를 다시 reverse하여 반환해주면 되는 것이다.

소스

public class Q2 {

	public static void main(String[] args) {
		String s = "in(f(lea)r)n)";
		// 결과 : "in(f(lea)r)n"
		System.out.println(solve(s));

	}

	public static String solve(String s) {
		// 문자열 입력을 받는 공간
		StringBuilder sb = new StringBuilder();
		// 결과 문자열 받는 공간
		StringBuilder result = new StringBuilder();

		// '('의 갯수
		int openBrace = 0;

		// openBrace 값 구하기
		for (char c : s.toCharArray()) {
			if (c == '(') {
				openBrace++;
			} else if (c == ')') {
				if (openBrace == 0) {
					continue;
				}

				openBrace--;
			}

			sb.append(c);
		}
		// 제외할 괄호 빼고 그대로 저장
		for (int i = sb.length() - 1; i >= 0; i--) {
			if (sb.charAt(i) == '(' && openBrace-- > 0) {
				continue;
			}
			result.append(sb.charAt(i));
		}

		return result.reverse().toString();
	}

}

3. indexOf(), substring()

문제)
앞자리 "te"를 반환

Input : String[] strs = {"test", "teacher"}
Output : "te"

풀이

  1. 첫번째 문자열인 "test"를 하나씩 줄여나감
  2. 줄여나가는 문자열을 남은 문자열과 indexOf()를 통해 비교
  3. substring()으로 "test"를 하나씩 줄여나감 "test" , "tes", "te"

소스

public class Q3 {

	public static void main(String[] args) {
		String[] strs = { "test", "teacher" };

		System.out.println(solve(strs));

	}

	public static String solve(String[] strs) {
		if (strs.length == 0) {
			return "";
		}

		// test
		String str1 = strs[0];

		for (int i = 1; i < strs.length; i++) {

			while (strs[i].indexOf(str1) != 0) {
				// test를 줄여나감
				str1 = str1.substring(0, str1.length() - 1);
			}
		}

		return str1;
	}

}

4. Longest Palindrome substring - index 이용

문제)
가장 긴 palindrome substring 을 반환

Input : String s = "bananas"
Output : "anana"

풀이

  1. 가장 긴 palindrome 문자열을 구해야 하기 때문에 start, end를 구해줘야 함
  2. 문자열의 첫번째 부터 양쪽 -1, +1 부분의 문자와 비교하여 start 와 end를 갱신
  3. end < (right - left -1) 부분을 통해서 가장 긴 부분을 저장
  4. start 와 end를 저장할 때 유의해서 저장

소스

public class Q4 {
	public static int start, end;

	public static String solve(String s) {
		int len = s.length();
		if (len < 2) {
			return s;
		}

		for (int i = 0; i < len - 1; i++) {
			// System.out.println((i + 1) + "번 째 --------------");
			findSubstring(s, i, i);
			findSubstring(s, i, i + 1);
		}

		return s.substring(start, start + end);
	}

	public static void findSubstring(String s, int left, int right) {
		// System.out.println("[while 전] left : " + left + " right : " + right);
		while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
			left--;
			right++;
		}
		// System.out.println("[while 후] left : " + left + " right : " + right);
		// System.out.println("right - left - 1 : " + (right - left - 1));
		if (end < right - left - 1) {
			end = right - left - 1;
			start = left + 1;
		}

		// System.out.println("start : " + start + " end : " + end);
	}

	public static void main(String[] args) {
		String s = "bananas";

		System.out.println(solve(s));
	}

}

참고

인프런 강의 : 코딩테스트 전 꼭 알아야 할 개념과 문제(with 자바) - 푸샵맨 코딩스터디

0개의 댓글