Leetcode [Greedy] 680. Valid Palindrome II [Easy]


Given a string s, return true if the s can be palindrome after deleting at most one character from it.

Example 1:   

Input: s = "aba"
Output: true  
Example 2:   

Input: s = "abca"
Output: true
Explanation: You could delete the character 'c'.
Example 3:   

Input: s = "abc"
Output: false
Constraints:

- 1 <= s.length <= 105.  
- s consists of lowercase English letters.    

문제설명

해당 문제는 주어진 문자열이 원래부터 palindrome이거나, 아닐경우, 최대 1개의 문자를 제거했을 때 palindrome이 되는지 확인하는 문제입니다.

palindrome : asdsa, aba, aabbcccbbaa eye 와 같이, 왼쪽에서 오른쪽으로 읽으나, 오른쪽에서 왼쪽으로 읽으나 같은 문자열이 되는 것을 말합니다.

해결방법

여기서 저는 two pointer를 사용하여, first는 처음에서 + 1씩 증가하여 오른쪽으로 이동하고,
last는 맨 마지막에서 -1 씩 감소하여 왼쪽으로 이동하면서,
앞뒤가 같은지 확인하는 isPalindrom 함수를 별도로 추가하여, 넘겨받은 문자열이 palidrome을 만족하는지 판단하도록 하였습니다.
그 후, 원래의 문자열도 동일하게 first와 last를 이용하여 앞뒤가 같은지를 확인하는 로직을 수행하도록 하였으며,

  • 같지 않을 경우

    현재 위치한 문자열 다음부터 마지막까지의 slice된 문자열을 넘겨주어 palindrome을 확인하거나, 현재 위치한 문자열부터 마지막 바로 전까지의 slice된 문자열을 넘겨주어 palindrome을 확인하여, 둘중 하나라도 true이면 true가 리턴됩니다.

  • 같을 경우

    first와 last의 인덱스를 각각 오른쪽, 왼쪽으로 옮겨서 다시 서로의 문자가 같은지 확인합니다.

 해당 이유는 최대 1개의 문자만 삭제할 수 있다는 조건때문에, 현재 first인덱스 다음글자부터 남은 문자열을 확인하거나,    
 현재 first인덱스부터 last인덱스 바로 앞까지 범위를 지정하여, 맨 마지막 글자를 제거한 남은 문자열을 확인하도록 하였습니다.   
 최초 답안 제출시에는, String을 Array로 변환하지 않고, string의 index 함수를 사용하여    
 문자열을 쪼개거나, 해당 first의 문자가 무엇인지, last의 문자가 무엇인지 늘 index를 계산해서 하는 방식으로 제출하였더니    
 시간초과가 나오는 것을 보고 Array로 변환해서 index에 바로 접근 하도록 불필요한 연산을 제거하고 제출에 성공하였습니다.   

swift 코드로 나타내면 아래와 같습니다.

class Solution {
    func validPalindrome(_ s: String) -> Bool {
        func isPalindrom(_ s: [String]) -> Bool {
            var first = 0
            var last = s.count - 1
            while first < last {
                if s[first] != s[last] {
                    return false
                } else {
                    first += 1
                    last -= 1
                }
            }
            return true
        }
        
        let stringArray = s.map { String($0) }
        var first = 0
        var last = stringArray.count - 1
        
        while first < last {
            if stringArray[first] != stringArray[last] {
                return isPalindrom(Array(stringArray[first + 1...last])) 
                       || isPalindrom(Array(stringArray[first...last - 1]))
            } else {
                first += 1
                last -= 1
            }
        }
        
        return true
    }*
}