1. 程式人生 > >Leetcode第1題至第10題 思路分析及C++實現

Leetcode第1題至第10題 思路分析及C++實現

mine long -c 一行 而且 特殊 頭部 根據 shard

筆者按照目錄刷題,對於每一道題,力爭使用效率最高(時間復雜度最低)的算法,並全部通過C++代碼實現AC。(文中計算的復雜度都是最壞情況復雜度)
因為考慮到大部分讀者已經在Leetcode瀏覽過題目了,所以每道題都按照 解題思路 -> 實現代碼 -> 問題描述 的順序進行講解。
(筆者目前已刷 40 題,已更新解法 10 題,最近一段時間會頻繁更新)可以點擊下方鏈接,直達gitbook:
https://codernie.gitbooks.io/leetcode-solutions/content/
也歡迎大家關註我的微信公眾號(大雄的學習人生),有問題可以隨時後臺回復我,多多探討。

目錄:

1 Two Sum

2 Add Two Numbers

3 Longest Substring Without Repeating Characters

4 Median of Two Sorted Arrays

5 Longest Palindromic Substring

6 ZigZag Conversion

7 Reverse Integer

8 String to Integer (atoi)

9 Palindrome Number

10 Regular Expression Match

1. Two Sum 【easy】

解題思路

暴力解法 O(N^2):

嵌套兩層循環:第一層:i 從 0 到 n - 2;第二層:j 從 i + 1 到 n - 1;判斷 nums[i] + nums[j] == target ,如果成立則是正確答案

map解法 O(N*logN)

從 0 到 n - 1 依次遍歷,利用map存放每一個數值的下標,在map中尋找是否有使(nums[i] + x == target)成立的x的存在,如果存在則返回i和它的下標(即myMap[ target - nums[i] ])。

復雜度分析:因為只遍歷了一次數組,map每次的查詢的時間復雜度為O(logN)所以整體復雜度為O(N*logN)、如果這裏使用hash_map可以將查詢復雜度降低到O(1),從而使得整體復雜度為O(N),但是hash_map不是標準的C++庫,所以這裏沒有使用。

實現代碼:

// 1. Two Sum
vector<int> twoSum(vector<int>& nums, int target) {
  map<int, int> myMap;
  vector<int> result;
  for (int i = 0; i < nums.size(); i++) {
    if (myMap.find(target - nums[i]) == myMap.end()) {
      myMap[nums[i]] = i;
    } else {
      result = {myMap[target - nums[i]], i};
      break;
    }
  }
  return result;
}

問題描述:

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have _exactly _one solution, and you may not use the_same_element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

2. Add Two Numbers【medium】

解題思路

從左到右遍歷鏈表,依次相加,每一個位置生成一個新的結點即可。

時間復雜度:O( max( len(l1), len(l2) ) )

考慮邊界條件:

1.進位的的處理:carry表示進位,當最後一位還有進位時,即使 l1 和 l2 均為NULL的情況下,還需要生成一個新的結點,所以while的條件中加入了 carry != 0 判斷項。

2.返回頭結點:當頭結點為NULL的時候記錄頭結點,並且讓p等於頭結點;後續情況讓 p->next 等於新的結點,並讓 p 指向 p->next。

實現代碼:

// 2. Add Two Numbers
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
  ListNode *head = NULL, *p;
  int carry = 0, sum;
  while (l1 != NULL || l2 != NULL || carry != 0) {
    sum = 0;
    if (l1 != NULL) {
      sum += l1->val;
      l1 = l1->next;
    }
    if (l2 != NULL) {
      sum += l2->val;
      l2 = l2->next;
    }
    sum += carry;
    carry = sum / 10;
    sum %= 10;
    ListNode *newNode = new ListNode(sum);
    if (head == NULL) {
      head = newNode;
      p = newNode;
    } else {
      p->next = newNode;   
      p = p->next;
    }
  }
  return head;
}

問題描述:

You are given two non-empty linked lists representing two non-negative integers. The digits are stored inreverse orderand each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Example

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.

3. Longest Substring Without Repeating Characters【medium】

解題思路

暴力解法 O(N^3):

從每個點遍歷、依次遍歷這個點後的每一個點、通過遍歷該點之前的點判斷該點是否出現過。聽上去有點拗口,代碼在下方,這個暴力方法Leetcode也可以AC,但是不推薦使用。

頭尾標記法 O(N*logN):

頭標記指向當前最長無重復字符串的頭部,尾標記指向其尾部。通過一個 map 來記錄出現過的字符最後出現的位置。

依次遍歷數組,如果當前字符已出現過,則讓頭標記指向其最後出現過的位置的後一個位置。然後每次通過頭、尾標記計算當前無重復字符串的長度,並與已知最大值作比較。這裏查詢map的復雜度為 O(logN),遍歷的復雜度為 O(N),因此整體復雜度為 O(N*logN)。如果這裏使用hash_map可以將查詢復雜度降低到O(1),從而使得整體復雜度為O(N),但是hash_map不是標準的C++庫,所以這裏沒有使用。

實現代碼:

// 3. Longest Substring Without Repeating Characters
// 暴力解法
int lengthOfLongestSubstring_bruteForce(string s) {
  int res = 0, sum;
  for (int i = s.size() - 1; i >= 0; i--) {
    sum = 1;
    for (int j = i - 1; j >= 0; j--) {
      bool flag = true;
      for (int k = i; k > j; k--) {
        if (s[j] == s[k]) {
          flag = false;
          break;
        }
      }
      if (flag) {
        sum++;
      } else {
        break;
      }
    }
    res = max(res, sum);
  }
  return res;      
}
// 頭尾標記法
int lengthOfLongestSubstring(string s) {
  map<char, int> myMap;
  int res = 0;
  for (int i = 0, j = 0; j < s.size(); j++){
    if (myMap.find(s[j]) != myMap.end()) {
      i = max(i, myMap[s[j]] + 1);
    }
    myMap[s[j]] = j;
    res = max(res, j - i + 1);
  }
  return res;
}

問題描述:

Given a string, find the length of thelongest substringwithout repeating characters.

Examples:

Given"abcabcbb", the answer is"abc", which the length is 3.

Given"bbbbb", the answer is"b", with the length of 1.

Given"pwwkew", the answer is"wke", with the length of 3. Note that the answer must be asubstring,"pwke"is asubsequenceand not a substring.

4. Median of Two Sorted Arrays【hard】

解題思路

這道題咋一看像二分查找,但是仔細看題,發現有兩個有序數組,而且不是讓我們找一個特定的數,而是要找兩個數組合並後的中位數,這樣一看就比較難了,也難怪歸類為hard類別。這道題除了一下介紹的二分查找法,還有兩個數組分別進行二分查找的方法,不過代碼量相對更多(也可能是因為筆者水平不夠導致代碼量過大),而且看了下面的二分查找法後,感嘆於該算法作者的腦洞,所以在這裏只介紹該種方法。

暴力方法 O((m + n)*log(m + n)):

將兩個數組合並,然後進行快排,中間的數即中位數。由於題目說了復雜度不能超過O(log(m + n)),所以這個方法當然回Time Limit Excess,所以我們得探究一種更高效的解法。

二分查找法 O(log(min(m, n))):

首先分別把兩個數組分成兩邊,大概為下面這種形式:(A表示nums1, B表示nums2)

          left_part          |        right_part
    A[0], A[1], ..., A[i-1]  |  A[i], A[i+1], ..., A[m-1]
    B[0], B[1], ..., B[j-1]  |  B[j], B[j+1], ..., B[n-1]

因為有序數列的性質,我們知道只要我們滿足以下兩個條件,我們就可以找到中位數了:

條件一:len(A_left) + len(B_left) = len(A_right) + len(B_right)

條件二:max[A_left, B_left] <= min[A_right, B_right]

為了使問題簡單化,我們先只考慮 m + n 為偶數的情況下,只要滿足上述兩個條件,我們的中位數就等於左邊的最大值加上右邊的最小值除以二。

為了滿足條件一,我們只要令** i + j == m + n - i - j (+ 1)**即可(這裏加一是為了之後考慮 m + n 為奇數的情況)

而為了滿足條件二,根據有序數組的性質,我們知道只需要滿足 A[i - 1] <= B[j] 且 B[j - 1] <= A[i] 即可。

接下來開始我們的算法探究:

假設我們首先隨機選擇一個 i (這裏 0 <= i < m),所以我們根據條件一,可以求得 j = (m + n + 1) / 2 - i;

為了滿足條件二,我們開始分別比較 A[i - 1] 與 B[j] 和 B[j - 1] 與 A[i]:

不難知道可能會有四種情況:

  • A[i - 1] <= B[j] 且 B[j - 1] <= A[i] :這不正是我們要找的 i 嗎?可以直接返回答案
  • A[i - 1] > B[j] 且 B[j - 1] > A[i] :根據有序數列的性質,再利用反證法不難證明這種情況不可能存在
  • A[i - 1] <= B[j] 且 B[j - 1] > A[i]:為了使情況更加接近我們的答案,也就是情況1。也就是要使 B[j - 1] <= A[i],因為現在 B[j - 1] > A[i],所以我們要想辦法縮小 B[j - 1],擴大A[i],所以當然是讓我們的 i 增大,否則情況會越來越遠離我們的正確答案。
  • A[i - 1] > B[j] 且 B[j - 1] <= A[i]:與情況3恰恰相反,這裏我們應該縮小我們的 i。

那我們如何縮小和擴大我們的 i 呢,那就是采用二分查找的方式啦,首先將 i 置為數組A的中間下標,如果需要增大,則把其設為上半區的中間下標,反之則設為下半區的中間下標,所以這種搜索方式的時間復雜度和二分查找的時間復雜度一樣,為了使時間復雜度盡量的小,我們使A成為長度更小的那個數組,如果初始A比B長,我們則交換它們的位置。

考慮邊界條件:

1.如果不存在滿足條件二的情況會怎麽樣呢?也就是 i 走到了數組A的盡頭,依舊沒法滿足條件二,這個時候我們不難知道如果 i 走到數組A的最左端,那麽它一定是在不斷地經歷情況4,而這時 A[0] > B[j],那麽我們不難知道這時left_part的最大值就是B[j - 1];反之我們也可以推出 i 到了A的最右端、j 到了B的最左端或者最右端的情況。

2.m + n 為奇數。這個時候我們不難推出 left_part 的最大值就是中位數。

3.A或B為空數組,因為當數組空的時候無法對數組進行下標訪問,所以我們在進行二分查找前就應該對該情況進行特殊處理,處理方式也是很簡單的啦。

實現代碼:

// 4. Median of Two Sorted Arrays
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
  // 使得 nums1 短於 nums2
  int m = nums1.size();
  int n = nums2.size();
  if (m > n) {
    vector<int> temp = nums1;
    nums1 = nums2;
    nums2 = temp;
    m = m + n;
    n = m - n;
    m = m - n;
  }
  // 考慮數組長度為0的邊界情況
  if (m == 0) {
    if (n == 0) {
      return 0;
    } else {
      if (n % 2 == 1) {
        return nums2[n / 2];
      } else {
        return (double)(nums2[n / 2] + nums2[n / 2 - 1]) / 2;
      }
    }
  }
  int iMin = 0, iMax = m, sizeSum = (m + n + 1) / 2, i, j;
  while (iMin <= iMax) {
    i = (iMax + iMin) / 2;
    j = sizeSum - i;
    if (nums2[j - 1] > nums1[i] && i < iMax) {
      iMin = i + 1;
    } else if (nums1[i - 1] > nums2[j] && i > iMin) {
      iMax = i - 1;
    } else {
      int maxLeft, minRight;
      if (i == 0) {
        maxLeft = nums2[j - 1];
      } else if (j == 0) {
        maxLeft = nums1[i - 1];
      } else {
        maxLeft = max(nums1[i - 1], nums2[j - 1]);
      }
      if ((m + n) % 2 == 1) {
        return maxLeft;
      }
      if (i == m) {
        minRight = nums2[j];
      } else if (j == n) {
        minRight = nums1[i];
      } else {
        minRight = min(nums1[i], nums2[j]);
      }
      return (double)(maxLeft + minRight) / 2;
    }
  }
  return 0;
}

問題描述:

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:

nums1 = [1, 3]
nums2 = [2]

The median is 2.0

Example 2:

nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

5. Longest Palindromic Substring【medium】

解題思路

暴力解法 O(N^3):

字符串有 n(n-1)/2 個子串,對每個子串進行檢測,看其是否是回文子串。因此復雜度為 O(N^3)。

從字符串中間開始擴展 O(N^2):

把字符串的每個點分別當成回文子串的中間點,開始往兩端擴展,不斷檢測,直到兩端不相等為止。因此復雜度為 O(N^2)。

動態規劃 O(N^2):

用 dp[i][j] 表示下標為 i 開頭 j 結尾的子串是否是回文子串。

轉移方程:dp[i][j] = (dp[i + 1][j - 1] && s[i] == s[j]) 【含義:當且僅當子串首尾兩端相等,且去除首尾兩端依舊是回文串時,該子串才會是回文串】

初始條件:對於每個長度為1的子串 dp[i][i] 都為回文串;對於每個長度為2的子串 dp[i][i + 1],當其首尾兩端相等時,其為回文串,否則不是。

實現代碼:

// 5. Longest Palindromic Substring (動態規劃)
string longestPalindrome(string s) {
  int length = s.size();
  if (length == 0) return s;
  int resI = 0, resJ = 0;
  bool dp[length + 1][length + 1];
  for (int i = 0; i <= length; i++)
    dp[i][i] = true;
  for (int i = 0; i < length; i++) {
    if (s[i] == s[i + 1]) {
      dp[i][i + 1] = true;
      if (resJ - resI < 1) {
        resI = i;
        resJ = i + 1;
      }
    } else {
      dp[i][i + 1] = false;
    }
  }
  for (int gap = 2; gap < length; gap++) {
    for (int i = 0; i + gap < length; i++) {
      int j = i + gap;
      if (s[i] == s[j] && dp[i + 1][j - 1]) {
        dp[i][j] = true;
        if (resJ - resI < j - i) {
          resI = i;
          resJ = j;
        }
      } else {
        dp[i][j] = false;
      }
    }
  }
  return s.substr(resI, resJ - resI + 1);
}

問題描述:

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example 1:

Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Example 2:

Input: "cbbd"
Output: "bb"

6. ZigZag Conversion【medium】

解題思路

這道題倒沒有特別的方法,就按照題目意思來模擬 Z 字形即可,用一個字符串數組來存放每一行的字符串,最後進行拼接即可。

考慮邊界條件:

當numRows等於1的時候,因為point無法增加也無法減小,所以沒辦法共用後面的代碼,考慮到numRows等於1的時候,答案就是原字符串,所以這裏直接返回s即可。

實現代碼:

// 6. ZigZag Conversion
string convert(string s, int numRows) {
  if (numRows == 1) return s;
  string res;
  bool shouldIncrease = true;
  string strArr[numRows];
  int point = 0;
  for (char c : s) {
    strArr[point] += c;
    if (point == numRows - 1) {
      shouldIncrease = false;
    } else if (point == 0) {
      shouldIncrease = true;
    }
    if (shouldIncrease) {
      point++;
    } else {
      point--;
    }
  }
  for (string str: strArr) {
    res += str;
  }
  return res;
}

問題描述:

The string"PAYPALISHIRING"is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P   A   H   N
A P L S I I G
Y   I   R

And then read line by line:"PAHNAPLSIIGYIR"

Write the code that will take a string and make this conversion given a number of rows:

string convert(string s, int numRows);

Example 1:

Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"

Example 2:

Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"

Explanation:
P     I    N
A   L S  I G
Y A   H R
P     I

7. Reverse Integer【easy】

解題思路

挨個遍歷,不斷把末位數賦給新的值即可。

考慮邊界條件:

當結果溢出時返回0,所以為了不讓中間值溢出,采用 long 類型來保存結果。

實現代碼:

// 7. Reverse Integer
int reverse(int x) {
  long result = 0, longX = abs((long)x);
  while (longX > 0) {
    result = result * 10 + longX % 10;
    longX /= 10;
  }
  result = (x > 0) ? result : -result;
  if (result > INT32_MAX || result < INT32_MIN) {
    return 0;
  } else {
    return (int)result;
  }
}

問題描述:

Given a 32-bit signed integer, reverse digits of an integer.

Example 1:

Input: 123
Output: 321

Example 2:

Input: -123
Output: -321

Example 3:

Input: 120
Output: 21

Note:
Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [?2^31, 2^31 ? 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.

8. String to Integer (atoi)【medium】

解題思路

遍歷字符串然後進行分情況討論:( isInit 表示數字是否已經開始,通過 isInit 的值判斷是否為開頭,如果為 true 表示不是開頭)

(1) 空格:如果為開頭空格則continue,否則跳出循環

(2) 正負號:如果為開頭正負號則設置isNeg的值,否則跳出循環

(3) 數字:將 isInit 置為true,累加結果

(4) 其他符號:跳出循環

考慮邊界條件:

當結果溢出時根據正負返回 INT32_MAX 或者 INT32_MIN,所以為了不讓中間值溢出,采用 long 類型來保存結果。

實現代碼:

// 8. String to Integer (atoi)
int myAtoi(string str) {
  long result = 0;
  bool isInit = false;
  bool isNeg = false;
  for (char c : str) {
    if (c == ‘ ‘) {
      if (isInit) {
        break;
      } else {
        continue;
      }
    } else if (c == ‘-‘ || c == ‘+‘) {
      if (!isInit) {
        isInit = true;
      } else {
        break;
      }
      isNeg = (c == ‘-‘);
    } else if (c >= 48 && c <= 57) {
      isInit = true;
      result = result * 10 + (c - 48);
      if (result > INT32_MAX) { 
        return isNeg ? INT32_MIN : INT32_MAX;
      }
    } else {
      break;
    }
  }      
  return (int)(isNeg ? -result : result);
}

問題描述:

Implementatoiwhich converts a string to an integer.

The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.

The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.

If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.

If no valid conversion could be performed, a zero value is returned.

Note:

  • Only the space character‘ ‘is considered as whitespace character.
  • Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [?2^31, 2^31 ? 1]. If the numerical value is out of the range of representable values, INT_MAX (2^31 ? 1) or INT_MIN (?2^31) is returned.

Example 1:

Input: "42"
Output: 42

Example 2:

Input: "   -42"
Output: -42
Explanation: The first non-whitespace character is ‘-‘, which is the minus sign.
             Then take as many numerical digits as possible, which gets 42.

Example 3:

Input: "4193 with words"
Output: 4193
Explanation: Conversion stops at digit ‘3‘ as the next character is not a numerical digit.

Example 4:

Input: "words and 987"
Output: 0
Explanation: The first non-whitespace character is ‘w‘, which is not a numerical 
             digit or a +/- sign. Therefore no valid conversion could be performed.

Example 5:

Input: "-91283472332"
Output: -2147483648
Explanation: The number "-91283472332" is out of the range of a 32-bit signed integer.
             Thefore INT_MIN (?231) is returned.

9. Palindrome Number【medium】

解題思路

利用第七題的代碼,將數字反轉,判斷與原數字是否相等即可,這裏考慮到負數全部都不是回文數字,所以直接返回false。

實現代碼:

// 9. Palindrome Number
int reverse(int x) {
  long result = 0, longX = abs((long)x);
  while (longX > 0) {
    result = result * 10 + longX % 10;
    longX /= 10;
  }
  result = (x > 0) ? result : -result;
  if (result > INT32_MAX || result < INT32_MIN) {
    return 0;
  } else {
    return (int)result;
  }
}
bool isPalindrome(int x) {
  if (x < 0) {
    return false;
  } else {
    return (x == reverse(x));
  }
}

問題描述:

Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward.

Example 1:

Input: 121
Output: true

Example 2:

Input: -121
Output: false
Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.

Example 3:

Input: 10
Output: false
Explanation: Reads 01 from right to left. Therefore it is not a palindrome.

Follow up:

Coud you solve it without converting the integer to a string?

10. Regular Expression Matching【hard】

解題思路

動態規劃思想解答這道題:

用 dp[i][j] 表示 s 的前 i 個字符組成的字符串和 p 的 前 j 個字符組成的字符串是否匹配。

轉移方程:

當 p[j - 1] == ‘*‘ 時:因為 * 可以表示匹配零位或者多位,正則匹配這裏要做貪心考慮,分三種情況,只要其中一種滿足即為true:

  • 匹配零位:則 dp[i][j] = dp[i][j - 2]
  • 匹配一位:則 dp[i][j] = dp[i - 1][j - 2] && (滿足最後一位匹配)
  • 匹配多位:則一位一位匹配,dp[i][j] = dp[i - 1][j] && (滿足最後一位匹配)

當 p[j - 1] != ‘*‘ 時,dp[i][j] 當且僅當 dp[i - 1][j - 1]為true時,並且最後一位匹配成功時,才為true。

初始狀態:

顯然,當 s 不為空,p 為空的時候dp[i][j] = false;

其次,當 s 為空,p不為空的時候,考慮到 * 可以匹配零位,所以利用狀態轉移方程判斷其是否應該為true。

實現代碼:

// 10. Regular Expression Matching
bool isMatch(string s, string p) {
  int n = s.size();
  int m = p.size();
  // initial
  bool dp[n + 1][m + 1];
  for (int i = 0; i < n + 1; i++) {
    for (int j = 0; j < m + 1; j++) {
      dp[i][j] = false;
    }
  }
  // start
  dp[0][0] = true;
  for (int i = 1; i < n + 1; i++) {
    dp[i][0] = false;
  }
  for (int j = 1; j < m + 1; j++) {
    if (j % 2 == 0) {
      dp[0][j] = dp[0][j - 2] && p[j - 1] == ‘*‘;
    } else {
      dp[0][j] = false;
    }
  }
  // trans
  bool compare;
  for (int i = 1; i < n + 1; i++) {
    for (int j = 1; j < m + 1; j++) {
      if (p[j - 1] != ‘*‘) {
        dp[i][j] = dp[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == ‘.‘);
      } else {
        compare = (s[i - 1] == p[j - 2] || p[j - 2] == ‘.‘);
        dp[i][j] = dp[i][j - 2] || (dp[i - 1][j - 2] && compare) || (dp[i - 1][j] && compare);
      }
    }
  }
  return dp[n][m];
}

問題描述:

Given an input string (s) and a pattern (p), implement regular expression matching with support for‘.‘and‘*‘.

‘.‘ Matches any single character.
‘*‘ Matches zero or more of the preceding element.

The matching should cover theentireinput string (not partial).

Note:

  • scould be empty and contains only lowercase lettersa-z
  • pcould be empty and contains only lowercase lettersa-z, and characters like . or *.

Example 1:

Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".

Example 2:

Input:
s = "aa"
p = "a*"
Output: true
Explanation: ‘*‘ means zero or more of the precedeng element, ‘a‘. Therefore, by repeating ‘a‘ once, it becomes "aa".

Example 3:

Input:
s = "ab"
p = ".*"
Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".

Example 4:

Input:
s = "aab"
p = "c*a*b"
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".

Example 5:

Input:
s = "mississippi"
p = "mis*is*p*."
Output: false

Leetcode第1題至第10題 思路分析及C++實現