LeetCode 14. 가장 긴 공통 접두어 긴 일반적인 접두사

가장 긴 일반적인 접두사

14. 가장 긴 공통 접두어

문자열 배열 사이 가장 긴 공통 접두어 문자열을 찾는 함수를 작성합니다.

공통 접두사가없는 경우 빈 문자열을 반환 "".

예 1 :

Input: ["flower","flow","flight"]
Output: "fl"

예 2 :

Input: ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.
수직 주사

각 문자열의 현재 위치를 나타내는 공통 포인터의 사용합니다. 템플릿으로 일치하는 첫 번째 문자열을 가져 가라. 나머지 문자열은 문자의 위치에 하나 하나와 일치와 템플릿 문자열의 처음부터 문자를 선택합니다. 경기가 성공하면, 다음 문자로 계속합니다. 그것이 실패하면 캐릭터의 성공을 일치하기 전에 문자열은 가장 긴 공통 접두어가 형성된다.

public String longestCommonPrefix(String[] strs) {
    if(strs == null || strs.length == 0){
        return "";
    }
    StringBuilder result = new StringBuilder();
    int strsSize = strs.length;
    int firstSize = strs[0].length();
    for(int i = 0; i < firstSize ; i++){
        char c = strs[0].charAt(i);
        for(int j = 1; j < strs.length; j++){
            if(i >= strs[j].length()) return result.toString();
            if(c != strs[j].charAt(i)) return result.toString();
        }
        result.append(c);
    }
    return result.toString();     
}

수평 주사

생각 수평 주사는 첫 번째 문자 문자열과 두 번째로 긴 접두어 문자열을 취득하고 다음 접두사 문자열과 문자열의 접두어 문자열을 찾는 것입니다. 가장 긴 접두어 문자열에 문자열의 모든을 통해 얻은 문자열을 통해 아래로 이러한 업데이트 접두어 문자열은이 그룹의 문자열입니다.

 public String longestCommonPrefix(String[] strs) {
    if (strs.length == 0) return "";
    String prefix = strs[0];
    for (int i = 1; i < strs.length; i++)
        while (strs[i].indexOf(prefix) != 0) {
            prefix = prefix.substring(0, prefix.length() - 1);
            if (prefix.isEmpty()) return "";
        }        
    return prefix;
}
분할 및 정복

수평 주사 방법들 사이에서, 우리는 일방적 인 조작을 찾을 수 있습니다 왼쪽에서 오른쪽으로, 경우는 스캔, 왼쪽에 사실, 우리는 오른쪽에서 스캔 결합 할 수 있습니다. 즉, 중간 검사 등을 동시에 양쪽. 은 분할 및 정복 소위. 시간 복잡도는

public String longestCommonPrefix(String[] strs) {
    if (strs == null || strs.length == 0) return "";    
        return longestCommonPrefix(strs, 0 , strs.length - 1);
}

private String longestCommonPrefix(String[] strs, int l, int r) {
    if (l == r) {
        return strs[l];
    }
    else {
        int mid = (l + r)/2;
        String lcpLeft =   longestCommonPrefix(strs, l , mid);
        String lcpRight =  longestCommonPrefix(strs, mid + 1,r);
        return commonPrefix(lcpLeft, lcpRight);
   }
}

String commonPrefix(String left,String right) {
    int min = Math.min(left.length(), right.length());       
    for (int i = 0; i < min; i++) {
        if ( left.charAt(i) != right.charAt(i) )
            return left.substring(0, i);
    }
    return left.substring(0, min);
}
이분법

우리는 공통 접두어 문자열의 관점에서 생각할 수 있습니다. 우선 가장 짧은 문자열은 최소 문자열을 충족해야합니다. 따라서, 우리는 먼저 템플릿, 다음 두 부분의 이분법으로 잘라 템플릿으로 최소 문자열 길이를 식별 할 수 있습니다. 그래서 당신은 직접 모든 문자열과 일치하도록 분할의 왼쪽 부분을 걸릴 수 있습니다. 경기가 성공할 수 있다면, 오른쪽, 왼쪽 부분과 일치하는의 오른쪽 부분을 분할합니다.

public String longestCommonPrefix(String[] strs) {
    if (strs == null || strs.length == 0)
        return "";
    int minLen = Integer.MAX_VALUE;
    for (String str : strs)
        minLen = Math.min(minLen, str.length());
    int low = 1;
    int high = minLen;
    while (low <= high) {
        int middle = (low + high) / 2;
        if (isCommonPrefix(strs, middle))
            low = middle + 1;
        else
            high = middle - 1;
    }
    return strs[0].substring(0, (low + high) / 2);
}

private boolean isCommonPrefix(String[] strs, int len){
    String str1 = strs[0].substring(0,len);
    for (int i = 1; i < strs.length; i++)
        if (!strs[i].startsWith(str1))
            return false;
    return true;
}
트라이 (접두사 나무)

사전 트리 시나리오는 많다. 이러한 등등 검색 엔진의 자동 채우기, 단어 맞춤법 검사, IP 경로 쿼리와 같은. 본질은 접두사 트라이 병합 함께입니다. 코어는 트라이 탐색 및 삽입 작업있다. 문자열을위한 템플릿, 문자열이 사전 트리로 구성되지 않기 때문에 우리는 재료를 선택합니다.

  • 삽입 작업 : 전체 문자열을 통과 할 필요가 삽입. 문자열의 문자를 들어, 문자열이 원래의 트리에 존재, 다음 루트 노드와 문자는 다음 문자를 통과하는 것을 계속한다. 원래 나무가이 노드에 존재하지 않을 경우,이 루트 노드로 간주되는 동안, 새로운 노드를 추가 통과하는 것을 계속한다.
  • 순회 작업이의 목적은 탐색 긴 접두사를 반환하는 것입니다. 따라서, 다음과 같은 네 가지 조건이 충족 긴 공통 접두어 탐색 종료
    • 사전에 잎 노드 탐색
    • 어린이 수는 두 개 이상의 노드를 통과하는
    • 마지막 문자열 템플릿에 트래버스
    • 횡단 문자가 존재하지 않습니다.
class Solution {
    class TrieNode {
        private TrieNode[] links;
        private final int R = 26;//表示26个字母
        private boolean isEnd;//表示是否为根节点
        int size = 0;
        
        public TrieNode() {
            links = new TrieNode[R];
        }
        public void put(char ch, TrieNode node){
            links[ch - 'a'] = node;
            ++size;
        }
        public int getLinks(){
           return size;
        }
        public boolean containsKey(char ch) {
            return links[ch - 'a'] != null;
        }
        public TrieNode get(char ch) {
            return links[ch - 'a'];
        }
        public void setEnd() {
            isEnd = true;
        }
        public boolean isEnd() {
            return isEnd;
        }
    }
    
    public class Trie {
        private TrieNode root;
        public Trie() {
            root = new TrieNode();
        }
        public void insert(String word) {
            TrieNode node = root;
            for(int i = 0; i < word.length(); ++i){
                char c = word.charAt(i);
                if(!node.containsKey(c)){
                    node.put(c, new TrieNode());    
                }
                node = node.get(c);
            }
            node.setEnd();
        }
        
        private String searchPrefix(String word) {
            TrieNode node = root;
            for(int i = 0; i < word.length(); ++i){
                char c = word.charAt(i);
                if(node.isEnd() || node.getLinks() > 1 || node.get(c) == null){
                    return word.substring(0, i);
                }
                node = node.get(c);
            }
            return word;
        }
    }
    
    public String longestCommonPrefix(String[] strs) {
        if(strs.length == 0) return "";
        if(strs.length == 1) return strs[0];
        
        Trie trie = new Trie();
        for(int i = 1; i < strs.length; ++i){
            trie.insert(strs[i]);
        }
        return trie.searchPrefix(strs[0]);
    }
}
게시 36 개 원래 기사 · 원 찬양 8 ·은 30000 +를 볼

추천

출처blog.csdn.net/qq_32763643/article/details/104167850