iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 6
0
自我挑戰組

新手也能學!一起從面試題理解程式邏輯!系列 第 6

【從面試題學邏輯-6】檢查單字大小寫是否合理(leetcode 520. Detect Capital)

↓點下方可以直接前往LeetCode
520. Detect Capital

簡單敘述題目:
給你一個字串,看看他的文法對不對,以下三種情況是對的

  1. 全都大寫
  2. 首字大寫,其他小寫
  3. 全部都小寫

那在開始前不乏提醒一下此系列的固定提醒:

這是一系列逐漸帶入解題的文章,難度會隨著進度增加,若還沒有讀過前面的文章,建議先從最前面開始來逐漸練習解題喔!


這一題其實可以直接用Character.isUpperCase()Character.isLowerCase(),再加上一大堆if來做判斷:

  • Character.isUpperCase() 可以判斷字元是不是大寫
  • Character.isLowerCase() 則是判斷字元是不是小寫

所以可以歸出以下邏輯:

  • 不到兩個字的話一定合格
  • 如果第一個字元是大寫...
    • 如果接下來都是大寫則合格
    • 如果接下來都是小寫則合格
  • 如果第一個字元是小寫...
    • 如果接下來都是小寫則合格
  • 其他全部不合格

那相信大家可以得出和筆者第一次解題的程式碼:

class Solution {
    public boolean detectCapitalUse(String word) {
        if(word.length()<2) return true; // 不到兩字算合格
        if(Character.isUpperCase(word.charAt(0))) {
        // 如果第一個字是大寫
            if(Character.isUpperCase(word.charAt(1))) {
            // 如果第二個字是大寫,接下來都要是大寫
                for(int i=2;i<word.length();i++) {
                    if(Character.isUpperCase(word.charAt(i)) != true) return false;
                }
                return true;
            } else {
            // 如果第二個字是小寫,接下來都要是小寫
                for(int i=2;i<word.length();i++) {
                    if(Character.isUpperCase(word.charAt(i))) return false;
                }
                return true;
            }
        } else {
        // 如果第一個字是小寫,接下來都要是小寫
            for(int i=1;i<word.length();i++) {
                if(Character.isUpperCase(word.charAt(i))) return false;
            }
            return true;
        }
    }
}

雖然是很快,但是這一串程式碼也真的是有夠長的
所以這裡要解釋另一種做法「正規表示式

我們這次先上程式碼再來和大家慢慢解釋:

class Solution {
    public boolean detectCapitalUse(String word) {
        return word.matches("[A-Z]*|[A-Z]?[a-z]*");
    }
}

絕大多數人看到上面一定是:
「這段程式碼到底是什麼東西!?」

簡單來說正規表示式是用來檢查輸入的東西,是否符合你所訂的規則

上面這題的規則還算簡單,但日後大家可能多少碰到要檢查是否符合某種格式的情況,用if else基本上就是地獄…。當然正規表示式要多難真的能多難,要看不懂真的完全看不懂,作為新手上路,我們稍微提一下這個大魔王,讓大家知道有這位魔王可以幫助你處理問題就好。

讓我們一步一步看上面這個判斷式吧!

先提一些符號說明:

  • | 代表 or ,請當成符合其中一者就算通過
  • *代表前面指定的表示式出現0次以上(可以不出現或出現很多次)
  • ?代表前面指定的表示式出現0或1次(可以不出現或出現1次)
  • [A-Z]代表字元A~Z中間的任意字元
  • [a-z]代表字元a~z中間的任意字元

接下來我們把這些符號與題目需求連結,大家可以一邊對著上面的說明來閱讀

  1. 先把[A-Z]*|[A-Z]?[a-z]*理解為符合[A-Z]*或是[A-Z]?[a-z]*的東西
  2. [A-Z]*代表這個字串必須符合
    • 字元A~Z中間的任意字元,出現0次或很多次
    • 這樣就符合全大寫的規定
  3. [A-Z]?[a-z]*代表說這個字串必須符合:
    • A到Z的字元先出現0~1次
    • 接著a~z的字元出現0次或很多次
    • 兩項組合在一起就可以符合首字大寫其他小寫,或是全小寫的規定

解決!


本文只是稍微提一下正規表示式的用法,個人相信已經有不少人頭暈眼花了
其實這個大魔王規則很多,組合更多,我們新手上路認識一下他就好,若有興趣的話請再自行搜尋相關資料來精進。


上一篇
【從面試題學邏輯-5】CTCI 1.2 如何判斷兩個字串是否互為排列組合
下一篇
【從面試題學邏輯-7】如果在矩陣內玩炸彈威力滿點的炸彈超人的話…(CTCI 1.8 矩陣清道夫)
系列文
新手也能學!一起從面試題理解程式邏輯!30

1 則留言

0
hk_escapee
iT邦新手 5 級 ‧ 2020-12-28 10:08:09

word.matches真的一行便可以了
我的做法:

class Solution {
    public boolean detectCapitalUse(String word) {
        char[] wordArr = word.toCharArray();
        int counter=0;
        for(int i=0;i<wordArr.length;i++){
            if(Character.isUpperCase(wordArr[i])){
                counter++;
            }
        }
        if(counter==0||counter==wordArr.length||(Character.isUpperCase(wordArr[0])&&counter==1)){
            return true;
        }
            return false;
    }
}

我要留言

立即登入留言